la-machina-engine 0.17.0 → 0.18.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.
package/dist/index.cjs CHANGED
@@ -3986,6 +3986,29 @@ var RunContext = class {
3986
3986
  });
3987
3987
  this.episodes?.logTurn(this.turnCount, "user", text2);
3988
3988
  }
3989
+ /**
3990
+ * Plan 051 — seed a prior chat turn into the run's message stack
3991
+ * before the current task. Writes a normal `user` / `assistant`
3992
+ * transcript entry so resume + inspect + compaction see the same
3993
+ * conversation the model saw, but intentionally:
3994
+ * - does NOT increment `turnCount` (a turn is a model response
3995
+ * this run produced, not historical context)
3996
+ * - does NOT log to `episodes` (avoid cross-run memory noise)
3997
+ *
3998
+ * Caller is responsible for validating role + content shape; this
3999
+ * helper just persists what it's given.
4000
+ */
4001
+ async seedInitialMessage(role, text2) {
4002
+ const content = [{ type: "text", text: text2 }];
4003
+ this.messages.push({ role, content });
4004
+ await this.writeEntry({
4005
+ type: role,
4006
+ uuid: this.nextUuid(),
4007
+ parentUuid: this.lastUuid,
4008
+ ts: this.now(),
4009
+ message: { role, content }
4010
+ });
4011
+ }
3989
4012
  async addAssistantMessage(content) {
3990
4013
  this.messages.push({ role: "assistant", content });
3991
4014
  await this.writeEntry({
@@ -10879,6 +10902,24 @@ function scrubRunOptions(opts) {
10879
10902
  }
10880
10903
  if (opts.compaction !== void 0) out.compaction = opts.compaction;
10881
10904
  if (opts.context !== void 0) out.context = { ...opts.context };
10905
+ if (opts.initialMessages !== void 0 && Array.isArray(opts.initialMessages)) {
10906
+ const roles = [];
10907
+ let totalChars = 0;
10908
+ for (const m of opts.initialMessages) {
10909
+ if (m === null || typeof m !== "object") continue;
10910
+ const role = m.role;
10911
+ const content = m.content;
10912
+ if (role !== "user" && role !== "assistant") continue;
10913
+ if (typeof content !== "string") continue;
10914
+ roles.push(role);
10915
+ totalChars += content.length;
10916
+ }
10917
+ out.initialMessages = {
10918
+ count: roles.length,
10919
+ roles,
10920
+ totalChars
10921
+ };
10922
+ }
10882
10923
  return out;
10883
10924
  }
10884
10925
  function serializeOutputSchema(schema) {
@@ -10954,6 +10995,14 @@ function rebuildMessagesFromEntries(entries) {
10954
10995
  return messages;
10955
10996
  }
10956
10997
 
10998
+ // src/engine/types.ts
10999
+ init_cjs_shims();
11000
+ var INITIAL_MESSAGES_LIMITS = {
11001
+ maxMessages: 100,
11002
+ maxTotalChars: 32e3,
11003
+ maxCharsPerMessage: 8e3
11004
+ };
11005
+
10957
11006
  // src/engine/response.ts
10958
11007
  init_cjs_shims();
10959
11008
  function toResponse(result, extra) {
@@ -11456,6 +11505,23 @@ var Engine = class {
11456
11505
  const runTimeout = this.startRunTimeout();
11457
11506
  try {
11458
11507
  await writer.setStatus("running");
11508
+ if (options.initialMessages !== void 0) {
11509
+ const validation = validateInitialMessages(options.initialMessages);
11510
+ if (!validation.ok) {
11511
+ await writer.setStatus("failed");
11512
+ return {
11513
+ runId,
11514
+ status: "failed",
11515
+ data: null,
11516
+ meta: { nodeId: options.nodeId, durationMs: Date.now() - startTime },
11517
+ errors: [{ code: "ERR_INVALID_INITIAL_MESSAGES", message: validation.message }],
11518
+ timestamp: Date.now()
11519
+ };
11520
+ }
11521
+ for (const m of validation.messages) {
11522
+ await ctx.seedInitialMessage(m.role, m.content);
11523
+ }
11524
+ }
11459
11525
  await dispatchHooks(this.config.hooks.preRun, {
11460
11526
  runId,
11461
11527
  nodeId: options.nodeId,
@@ -12962,6 +13028,60 @@ function buildToolRegistry(options) {
12962
13028
  }
12963
13029
  return registry;
12964
13030
  }
13031
+ function validateInitialMessages(raw) {
13032
+ if (!Array.isArray(raw)) {
13033
+ return { ok: false, message: "initialMessages must be an array" };
13034
+ }
13035
+ const { maxMessages, maxTotalChars, maxCharsPerMessage } = INITIAL_MESSAGES_LIMITS;
13036
+ if (raw.length > maxMessages) {
13037
+ return {
13038
+ ok: false,
13039
+ message: `initialMessages exceeds max of ${String(maxMessages)} messages (got ${String(raw.length)})`
13040
+ };
13041
+ }
13042
+ const out = [];
13043
+ let totalChars = 0;
13044
+ for (let i = 0; i < raw.length; i++) {
13045
+ const m = raw[i];
13046
+ if (m === null || typeof m !== "object") {
13047
+ return { ok: false, message: `initialMessages[${String(i)}] must be an object` };
13048
+ }
13049
+ if (m.role !== "user" && m.role !== "assistant") {
13050
+ return {
13051
+ ok: false,
13052
+ message: `initialMessages[${String(i)}].role must be 'user' or 'assistant'`
13053
+ };
13054
+ }
13055
+ if (typeof m.content !== "string") {
13056
+ return {
13057
+ ok: false,
13058
+ message: `initialMessages[${String(i)}].content must be a string`
13059
+ };
13060
+ }
13061
+ const trimmed = m.content.trim();
13062
+ if (trimmed.length === 0) {
13063
+ return {
13064
+ ok: false,
13065
+ message: `initialMessages[${String(i)}].content must not be empty`
13066
+ };
13067
+ }
13068
+ if (trimmed.length > maxCharsPerMessage) {
13069
+ return {
13070
+ ok: false,
13071
+ message: `initialMessages[${String(i)}].content exceeds ${String(maxCharsPerMessage)} chars`
13072
+ };
13073
+ }
13074
+ totalChars += trimmed.length;
13075
+ if (totalChars > maxTotalChars) {
13076
+ return {
13077
+ ok: false,
13078
+ message: `initialMessages total content exceeds ${String(maxTotalChars)} chars`
13079
+ };
13080
+ }
13081
+ out.push({ role: m.role, content: trimmed });
13082
+ }
13083
+ return { ok: true, messages: out };
13084
+ }
12965
13085
 
12966
13086
  // src/index.ts
12967
13087
  init_contract();