perstack 0.0.121 → 0.0.123

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/bin/cli.js CHANGED
@@ -21327,7 +21327,7 @@ async function expertVersionsHandler(scopeName, options) {
21327
21327
 
21328
21328
  //#endregion
21329
21329
  //#region ../../packages/runtime/package.json
21330
- var version$1 = "0.0.133";
21330
+ var version$1 = "0.0.134";
21331
21331
 
21332
21332
  //#endregion
21333
21333
  //#region ../../packages/runtime/src/helpers/usage.ts
@@ -89359,6 +89359,8 @@ const PROVIDERS_WITHOUT_REASONING_HISTORY = [
89359
89359
  "deepseek",
89360
89360
  "ollama"
89361
89361
  ];
89362
+ /** Providers that don't handle multiple consecutive system messages well */
89363
+ const PROVIDERS_REQUIRING_MERGED_SYSTEM_MESSAGES = ["openai", "azure-openai"];
89362
89364
  /**
89363
89365
  * Filter out reasoning parts from messages for providers that don't support them.
89364
89366
  * This prevents "Non-OpenAI reasoning parts are not supported" warnings from AI SDK.
@@ -89377,6 +89379,43 @@ function filterReasoningPartsForProvider(messages, providerName) {
89377
89379
  };
89378
89380
  });
89379
89381
  }
89382
+ /**
89383
+ * Merge consecutive system messages into a single message for providers that
89384
+ * don't support multiple system/developer messages (e.g., OpenAI reasoning models).
89385
+ * Preserves providerOptions from the last message in each group.
89386
+ */
89387
+ function mergeConsecutiveSystemMessages(messages, providerName) {
89388
+ if (!PROVIDERS_REQUIRING_MERGED_SYSTEM_MESSAGES.includes(providerName)) return messages;
89389
+ const result = [];
89390
+ let systemGroup = [];
89391
+ const flushSystemGroup = () => {
89392
+ if (systemGroup.length === 0) return;
89393
+ if (systemGroup.length === 1) result.push({
89394
+ role: "system",
89395
+ content: systemGroup[0].content,
89396
+ providerOptions: systemGroup[0].providerOptions
89397
+ });
89398
+ else {
89399
+ const lastOptions = systemGroup[systemGroup.length - 1].providerOptions;
89400
+ result.push({
89401
+ role: "system",
89402
+ content: systemGroup.map((m) => m.content).join("\n\n"),
89403
+ providerOptions: lastOptions
89404
+ });
89405
+ }
89406
+ systemGroup = [];
89407
+ };
89408
+ for (const message of messages) if (message.role === "system") systemGroup.push({
89409
+ content: message.content,
89410
+ providerOptions: message.providerOptions
89411
+ });
89412
+ else {
89413
+ flushSystemGroup();
89414
+ result.push(message);
89415
+ }
89416
+ flushSystemGroup();
89417
+ return result;
89418
+ }
89380
89419
  var LLMExecutor = class {
89381
89420
  constructor(adapter, model) {
89382
89421
  this.adapter = adapter;
@@ -89387,7 +89426,7 @@ var LLMExecutor = class {
89387
89426
  const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
89388
89427
  const reasoningOptions = shouldEnableReasoning(params.reasoningBudget) && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
89389
89428
  const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
89390
- const messages = filterReasoningPartsForProvider(params.messages, this.adapter.providerName);
89429
+ const messages = mergeConsecutiveSystemMessages(filterReasoningPartsForProvider(params.messages, this.adapter.providerName), this.adapter.providerName);
89391
89430
  try {
89392
89431
  return {
89393
89432
  success: true,
@@ -89426,7 +89465,7 @@ var LLMExecutor = class {
89426
89465
  const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
89427
89466
  const reasoningOptions = shouldEnableReasoning(params.reasoningBudget) && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
89428
89467
  const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
89429
- const messages = filterReasoningPartsForProvider(params.messages, this.adapter.providerName);
89468
+ const messages = mergeConsecutiveSystemMessages(filterReasoningPartsForProvider(params.messages, this.adapter.providerName), this.adapter.providerName);
89430
89469
  try {
89431
89470
  return {
89432
89471
  success: true,
@@ -89451,7 +89490,7 @@ var LLMExecutor = class {
89451
89490
  const baseProviderOptions = this.adapter.getProviderOptions(params.providerOptionsConfig);
89452
89491
  const reasoningOptions = shouldEnableReasoning(params.reasoningBudget) && params.reasoningBudget ? this.adapter.getReasoningOptions(params.reasoningBudget) : void 0;
89453
89492
  const providerOptions = this.mergeProviderOptions(baseProviderOptions, reasoningOptions);
89454
- const messages = filterReasoningPartsForProvider(params.messages, this.adapter.providerName);
89493
+ const messages = mergeConsecutiveSystemMessages(filterReasoningPartsForProvider(params.messages, this.adapter.providerName), this.adapter.providerName);
89455
89494
  const streamResult = streamText({
89456
89495
  model: this.model,
89457
89496
  messages,
@@ -92621,49 +92660,8 @@ async function callingInteractiveToolsLogic({ setting, checkpoint, step }) {
92621
92660
  });
92622
92661
  }
92623
92662
 
92624
- //#endregion
92625
- //#region ../../node_modules/.bun/ts-dedent@2.2.0/node_modules/ts-dedent/dist/index.js
92626
- var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
92627
- Object.defineProperty(exports, "__esModule", { value: true });
92628
- exports.dedent = void 0;
92629
- function dedent(templ) {
92630
- var values = [];
92631
- for (var _i = 1; _i < arguments.length; _i++) values[_i - 1] = arguments[_i];
92632
- var strings = Array.from(typeof templ === "string" ? [templ] : templ);
92633
- strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, "");
92634
- var indentLengths = strings.reduce(function(arr, str) {
92635
- var matches = str.match(/\n([\t ]+|(?!\s).)/g);
92636
- if (matches) return arr.concat(matches.map(function(match) {
92637
- var _a, _b;
92638
- return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
92639
- }));
92640
- return arr;
92641
- }, []);
92642
- if (indentLengths.length) {
92643
- var pattern_1 = new RegExp("\n[ ]{" + Math.min.apply(Math, indentLengths) + "}", "g");
92644
- strings = strings.map(function(str) {
92645
- return str.replace(pattern_1, "\n");
92646
- });
92647
- }
92648
- strings[0] = strings[0].replace(/^\r?\n/, "");
92649
- var string = strings[0];
92650
- values.forEach(function(value, i) {
92651
- var endentations = string.match(/(?:^|\n)( *)$/);
92652
- var endentation = endentations ? endentations[1] : "";
92653
- var indentedValue = value;
92654
- if (typeof value === "string" && value.includes("\n")) indentedValue = String(value).split("\n").map(function(str, i) {
92655
- return i === 0 ? str : "" + endentation + str;
92656
- }).join("\n");
92657
- string += indentedValue + strings[i + 1];
92658
- });
92659
- return string;
92660
- }
92661
- exports.dedent = dedent;
92662
- }));
92663
-
92664
92663
  //#endregion
92665
92664
  //#region ../../packages/runtime/src/messages/message.ts
92666
- var import_dist = require_dist();
92667
92665
  function createUserMessage(contents) {
92668
92666
  return {
92669
92667
  type: "userMessage",
@@ -92700,36 +92698,31 @@ function createToolMessage(contents) {
92700
92698
  }
92701
92699
  function messageToCoreMessage(message) {
92702
92700
  switch (message.type) {
92703
- case "instructionMessage": return {
92704
- role: "system",
92705
- content: instructionContentsToCoreContent(message.contents),
92706
- providerOptions: message.cache ? { anthropic: { cacheControl: { type: "ephemeral" } } } : void 0
92707
- };
92708
- case "userMessage": return {
92701
+ case "instructionMessage": {
92702
+ const { contents, cache } = message;
92703
+ return contents.map((part, index) => ({
92704
+ role: "system",
92705
+ content: part.text,
92706
+ providerOptions: cache && index === contents.length - 1 ? { anthropic: { cacheControl: { type: "ephemeral" } } } : void 0
92707
+ }));
92708
+ }
92709
+ case "userMessage": return [{
92709
92710
  role: "user",
92710
92711
  content: userContentsToCoreContent(message.contents),
92711
92712
  providerOptions: message.cache ? { anthropic: { cacheControl: { type: "ephemeral" } } } : void 0
92712
- };
92713
- case "expertMessage": return {
92713
+ }];
92714
+ case "expertMessage": return [{
92714
92715
  role: "assistant",
92715
92716
  content: expertContentsToCoreContent(message.contents),
92716
92717
  providerOptions: message.cache ? { anthropic: { cacheControl: { type: "ephemeral" } } } : void 0
92717
- };
92718
- case "toolMessage": return {
92718
+ }];
92719
+ case "toolMessage": return [{
92719
92720
  role: "tool",
92720
92721
  content: toolContentsToCoreContent(message.contents),
92721
92722
  providerOptions: message.cache ? { anthropic: { cacheControl: { type: "ephemeral" } } } : void 0
92722
- };
92723
+ }];
92723
92724
  }
92724
92725
  }
92725
- function instructionContentsToCoreContent(contents) {
92726
- return contents.reduce((acc, part) => {
92727
- return import_dist.dedent`
92728
- ${acc}
92729
- ${part.text}
92730
- `.trim();
92731
- }, "");
92732
- }
92733
92726
  function userContentsToCoreContent(contents) {
92734
92727
  return contents.map((part) => {
92735
92728
  switch (part.type) {
@@ -93032,7 +93025,7 @@ async function generatingToolCallLogic({ setting, checkpoint, step, skillManager
93032
93025
  const { messages } = checkpoint;
93033
93026
  let reasoningCompletedViaCallback = false;
93034
93027
  const executionResult = await llmExecutor.streamText({
93035
- messages: messages.map(messageToCoreMessage),
93028
+ messages: messages.flatMap(messageToCoreMessage),
93036
93029
  maxRetries: setting.maxRetries,
93037
93030
  tools: getToolSet(skillManager),
93038
93031
  toolChoice: "auto",
@@ -93252,8 +93245,54 @@ async function generatingToolCallLogic({ setting, checkpoint, step, skillManager
93252
93245
  throw new Error(`Unexpected finish reason: ${finishReason}`);
93253
93246
  }
93254
93247
 
93248
+ //#endregion
93249
+ //#region ../../node_modules/.bun/ts-dedent@2.2.0/node_modules/ts-dedent/dist/index.js
93250
+ var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
93251
+ Object.defineProperty(exports, "__esModule", { value: true });
93252
+ exports.dedent = void 0;
93253
+ function dedent(templ) {
93254
+ var values = [];
93255
+ for (var _i = 1; _i < arguments.length; _i++) values[_i - 1] = arguments[_i];
93256
+ var strings = Array.from(typeof templ === "string" ? [templ] : templ);
93257
+ strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, "");
93258
+ var indentLengths = strings.reduce(function(arr, str) {
93259
+ var matches = str.match(/\n([\t ]+|(?!\s).)/g);
93260
+ if (matches) return arr.concat(matches.map(function(match) {
93261
+ var _a, _b;
93262
+ return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
93263
+ }));
93264
+ return arr;
93265
+ }, []);
93266
+ if (indentLengths.length) {
93267
+ var pattern_1 = new RegExp("\n[ ]{" + Math.min.apply(Math, indentLengths) + "}", "g");
93268
+ strings = strings.map(function(str) {
93269
+ return str.replace(pattern_1, "\n");
93270
+ });
93271
+ }
93272
+ strings[0] = strings[0].replace(/^\r?\n/, "");
93273
+ var string = strings[0];
93274
+ values.forEach(function(value, i) {
93275
+ var endentations = string.match(/(?:^|\n)( *)$/);
93276
+ var endentation = endentations ? endentations[1] : "";
93277
+ var indentedValue = value;
93278
+ if (typeof value === "string" && value.includes("\n")) indentedValue = String(value).split("\n").map(function(str, i) {
93279
+ return i === 0 ? str : "" + endentation + str;
93280
+ }).join("\n");
93281
+ string += indentedValue + strings[i + 1];
93282
+ });
93283
+ return string;
93284
+ }
93285
+ exports.dedent = dedent;
93286
+ }));
93287
+
93255
93288
  //#endregion
93256
93289
  //#region ../../packages/runtime/src/messages/instruction-message.ts
93290
+ var import_dist = require_dist();
93291
+ function getEnvironmentSection(startedAt) {
93292
+ const lines = [`- Current time: ${new Date(startedAt).toISOString()}`, `- Working directory: ${process.cwd()}`];
93293
+ if (process.env.PERSTACK_SANDBOX === "1") lines.push("- Sandbox: This is an isolated container environment (Ubuntu). You can freely install packages with `sudo apt-get install` and run arbitrary commands without affecting the host system.");
93294
+ return `Environment:\n${lines.join("\n")}`;
93295
+ }
93257
93296
  function getDelegateMetaInstruction(startedAt) {
93258
93297
  return import_dist.dedent`
93259
93298
  Before starting work, investigate the workspace and understand the current state. Then use the todo tool to create a plan of action. Work through the todos step by step, marking each completed as you go.
@@ -93261,9 +93300,7 @@ function getDelegateMetaInstruction(startedAt) {
93261
93300
  When the task is complete, call attemptCompletion with a result parameter containing your final response.
93262
93301
  When you cannot help, call attemptCompletion without a result.
93263
93302
 
93264
- Environment:
93265
- - Current time: ${new Date(startedAt).toISOString()}
93266
- - Working directory: ${process.cwd()}
93303
+ ${getEnvironmentSection(startedAt)}
93267
93304
  `;
93268
93305
  }
93269
93306
  function getCoordinatorMetaInstruction(startedAt) {
@@ -93302,32 +93339,33 @@ function getCoordinatorMetaInstruction(startedAt) {
93302
93339
  When the task is complete, call attemptCompletion with a result parameter containing your final response.
93303
93340
  When you cannot help, call attemptCompletion without a result.
93304
93341
 
93305
- Environment:
93306
- - Current time: ${new Date(startedAt).toISOString()}
93307
- - Working directory: ${process.cwd()}
93342
+ ${getEnvironmentSection(startedAt)}
93308
93343
  `;
93309
93344
  }
93310
93345
  function createInstructionMessage(expert, startedAt) {
93311
- const instruction = import_dist.dedent`
93346
+ const preamble = import_dist.dedent`
93312
93347
  You are Perstack, an AI expert that tackles tasks requested by users by utilizing all available tools.
93313
93348
 
93314
93349
  ${isCoordinatorExpert(expert.name) ? getCoordinatorMetaInstruction(startedAt) : getDelegateMetaInstruction(startedAt)}
93315
-
93316
- ---
93317
-
93318
- ${expert.instruction}
93319
-
93320
- ---
93321
-
93322
- ${getSkillRules(expert)}
93323
93350
  `;
93351
+ const contents = [{
93352
+ id: createId(),
93353
+ type: "textPart",
93354
+ text: preamble
93355
+ }, {
93356
+ id: createId(),
93357
+ type: "textPart",
93358
+ text: expert.instruction
93359
+ }];
93360
+ const skillRules = getSkillRules(expert);
93361
+ if (skillRules) contents.push({
93362
+ id: createId(),
93363
+ type: "textPart",
93364
+ text: skillRules
93365
+ });
93324
93366
  return {
93325
93367
  type: "instructionMessage",
93326
- contents: [{
93327
- id: createId(),
93328
- type: "textPart",
93329
- text: instruction
93330
- }],
93368
+ contents,
93331
93369
  id: createId()
93332
93370
  };
93333
93371
  }
@@ -122908,7 +122946,7 @@ async function startHandler(expertKey, query, options, handlerOptions) {
122908
122946
  //#endregion
122909
122947
  //#region package.json
122910
122948
  var name = "perstack";
122911
- var version = "0.0.121";
122949
+ var version = "0.0.123";
122912
122950
  var description = "PerStack CLI";
122913
122951
 
122914
122952
  //#endregion