perchai-cli 2.4.52 → 2.4.54

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 (2) hide show
  1. package/dist/perch.mjs +89 -33
  2. package/package.json +1 -1
package/dist/perch.mjs CHANGED
@@ -75908,6 +75908,7 @@ var init_payroll = __esm({
75908
75908
  // lib/perchBusinessTools/index.ts
75909
75909
  var init_perchBusinessTools = __esm({
75910
75910
  "lib/perchBusinessTools/index.ts"() {
75911
+ "use strict";
75911
75912
  init_generateAPAuditPacket();
75912
75913
  init_inventoryFolder();
75913
75914
  init_loadBusinessTables();
@@ -76259,6 +76260,7 @@ function isTurnAbortedError(error) {
76259
76260
  var TURN_STOPPED_BY_USER_MESSAGE;
76260
76261
  var init_turnAbort = __esm({
76261
76262
  "features/perchTerminal/runtime/turnAbort.ts"() {
76263
+ "use strict";
76262
76264
  TURN_STOPPED_BY_USER_MESSAGE = "Turn stopped by user.";
76263
76265
  }
76264
76266
  });
@@ -76564,7 +76566,6 @@ function getToolDisplayName(toolName) {
76564
76566
  var NON_MODULE_TOOL_OWNERS, TOOL_RISK, TOOL_DISPLAY_NAMES;
76565
76567
  var init_catalog = __esm({
76566
76568
  "features/perchTerminal/runtime/toolSystem/catalog.ts"() {
76567
- "use strict";
76568
76569
  init_toolNames();
76569
76570
  NON_MODULE_TOOL_OWNERS = {
76570
76571
  [TOOL_NAMES.listSources]: "lane",
@@ -84012,6 +84013,7 @@ function listWorkerContracts() {
84012
84013
  }
84013
84014
  var init_workerManifest = __esm({
84014
84015
  "features/perchTerminal/runtime/workers/workerManifest.ts"() {
84016
+ "use strict";
84015
84017
  init_managedWorkflowRegistry();
84016
84018
  init_platformRoles();
84017
84019
  init_financialRoles();
@@ -87169,7 +87171,6 @@ function truncateHistoryLine(value, max2) {
87169
87171
  }
87170
87172
  var init_operatorTruth = __esm({
87171
87173
  "features/perchTerminal/runtime/operatorTruth.ts"() {
87172
- "use strict";
87173
87174
  }
87174
87175
  });
87175
87176
 
@@ -91720,6 +91721,7 @@ Final answers lead with findings, name artifacts or delivery status, and give on
91720
91721
  var MARKET_DESK_TOOL_NAMES;
91721
91722
  var init_marketDeskAccess = __esm({
91722
91723
  "features/perchTerminal/runtime/marketDesk/marketDeskAccess.ts"() {
91724
+ "use strict";
91723
91725
  init_toolNames();
91724
91726
  MARKET_DESK_TOOL_NAMES = /* @__PURE__ */ new Set([
91725
91727
  TOOL_NAMES.getMarketSignal,
@@ -200020,7 +200022,6 @@ function dedupeEvidence(items) {
200020
200022
  var packetStore, ROLE_KIND_MAP, DOWNSTREAM_CONSUMERS, URL_PATTERN, MARKDOWN_LINK_PATTERN;
200021
200023
  var init_contextPackets = __esm({
200022
200024
  "features/perchTerminal/agentPlatform/contextPackets.ts"() {
200023
- "use strict";
200024
200025
  packetStore = /* @__PURE__ */ new Map();
200025
200026
  ROLE_KIND_MAP = {
200026
200027
  legal_source_scout: "research",
@@ -210204,25 +210205,61 @@ var init_workGraph = __esm({
210204
210205
  });
210205
210206
 
210206
210207
  // features/perchTerminal/runtime/parseModelJson.ts
210207
- function extractJsonFromText(text) {
210208
- const trimmed = text.trim();
210209
- if (!trimmed) return null;
210210
- const fenceMatch = trimmed.match(/^```(?:json)?\s*\n?([\s\S]*?)```\s*$/);
210211
- if (fenceMatch?.[1]) return fenceMatch[1].trim();
210212
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) return trimmed;
210213
- const innerMatch = trimmed.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
210214
- if (innerMatch?.[1]) return innerMatch[1];
210215
- return null;
210208
+ function stripReasoningWrappers(text) {
210209
+ return text.replace(/<think>[\s\S]*?<\/think>/gi, " ").replace(/<thinking>[\s\S]*?<\/thinking>/gi, " ").replace(/<reasoning>[\s\S]*?<\/reasoning>/gi, " ").replace(/<\/?(?:think|thinking|reasoning)>/gi, " ");
210210
+ }
210211
+ function balancedJsonObjects(text) {
210212
+ const out = [];
210213
+ let depth = 0;
210214
+ let start = -1;
210215
+ let inString = false;
210216
+ let escaped = false;
210217
+ for (let i = 0; i < text.length; i++) {
210218
+ const ch = text[i];
210219
+ if (inString) {
210220
+ if (escaped) escaped = false;
210221
+ else if (ch === "\\") escaped = true;
210222
+ else if (ch === '"') inString = false;
210223
+ continue;
210224
+ }
210225
+ if (ch === '"') {
210226
+ inString = true;
210227
+ } else if (ch === "{") {
210228
+ if (depth === 0) start = i;
210229
+ depth++;
210230
+ } else if (ch === "}" && depth > 0) {
210231
+ depth--;
210232
+ if (depth === 0 && start >= 0) {
210233
+ out.push(text.slice(start, i + 1));
210234
+ start = -1;
210235
+ }
210236
+ }
210237
+ }
210238
+ return out;
210239
+ }
210240
+ function jsonCandidates(text) {
210241
+ const candidates = [];
210242
+ const stripped = stripReasoningWrappers(text).trim();
210243
+ if (!stripped) return candidates;
210244
+ const fenceMatch = stripped.match(/```(?:json)?\s*\n?([\s\S]*?)```/i);
210245
+ if (fenceMatch?.[1]?.trim()) candidates.push(fenceMatch[1].trim());
210246
+ if (stripped.startsWith("{") || stripped.startsWith("[")) candidates.push(stripped);
210247
+ for (const obj2 of balancedJsonObjects(stripped).sort((a, b2) => b2.length - a.length)) {
210248
+ candidates.push(obj2);
210249
+ }
210250
+ const greedy = stripped.match(/\{[\s\S]*\}|\[[\s\S]*\]/);
210251
+ if (greedy?.[0]) candidates.push(greedy[0]);
210252
+ return candidates;
210216
210253
  }
210217
210254
  function parseStructuredRecordFromModelText(text) {
210218
- const raw = extractJsonFromText(text);
210219
- if (!raw) return null;
210220
- try {
210221
- const parsed = JSON.parse(raw);
210222
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
210223
- return parsed;
210255
+ for (const candidate of jsonCandidates(text)) {
210256
+ try {
210257
+ const parsed = JSON.parse(candidate);
210258
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
210259
+ return parsed;
210260
+ }
210261
+ } catch {
210224
210262
  }
210225
- } catch {
210226
210263
  }
210227
210264
  return null;
210228
210265
  }
@@ -225499,6 +225536,8 @@ async function runFlockTurn(input, deps, options = {}) {
225499
225536
  ensureFlockWorkersRegistered();
225500
225537
  const planStartMs = Date.now();
225501
225538
  let plan = null;
225539
+ let plannerRawSnippet = "";
225540
+ let plannerTimedOut = false;
225502
225541
  if (options.plannerModelCall !== null) {
225503
225542
  const llmCtx = {
225504
225543
  task,
@@ -225506,13 +225545,20 @@ async function runFlockTurn(input, deps, options = {}) {
225506
225545
  surface: detectFlockSurface(),
225507
225546
  turnInput: input
225508
225547
  };
225509
- const modelCall = options.plannerModelCall ?? defaultFlockPlannerModelCall(llmCtx);
225548
+ const baseModelCall = options.plannerModelCall ?? defaultFlockPlannerModelCall(llmCtx);
225549
+ const modelCall = async (prompts) => {
225550
+ const result2 = await baseModelCall(prompts);
225551
+ plannerRawSnippet = (result2.text ?? "").trim().slice(0, 600);
225552
+ return result2;
225553
+ };
225510
225554
  const plannerTimeoutMs = options.plannerTimeoutMs ?? FLOCK_PLANNER_TIMEOUT_MS;
225511
225555
  const first2 = await runLlmPlannerWithTimeout(llmCtx, modelCall, plannerTimeoutMs);
225512
225556
  plan = first2.plan;
225557
+ plannerTimedOut = first2.timedOut;
225513
225558
  if (!plan && !first2.timedOut) {
225514
225559
  const retry = await runLlmPlannerWithTimeout(llmCtx, modelCall, plannerTimeoutMs);
225515
225560
  plan = retry.plan;
225561
+ plannerTimedOut = retry.timedOut;
225516
225562
  }
225517
225563
  }
225518
225564
  if (!plan) {
@@ -225539,12 +225585,10 @@ async function runFlockTurn(input, deps, options = {}) {
225539
225585
  );
225540
225586
  }
225541
225587
  const modelOverrides = plan.accepted ? applyFlockModelOverrides(plan, task) : { applied: [], unavailable: [] };
225542
- emit({
225543
- type: "diagnostic",
225544
- code: "flock_planner_outcome",
225545
- message: `planner source=${plan.source} accepted=${plan.accepted} workers=${plan.accepted ? plan.workers.length : 0} elapsed=${Date.now() - planStartMs}ms`,
225546
- ts: now11()
225547
- });
225588
+ const plannerReason = plannerTimedOut ? "timeout" : plan.accepted ? "ok" : plannerRawSnippet ? "unparseable_or_invalid" : "empty_or_error";
225589
+ const plannerTraceMsg = `planner source=${plan.source} accepted=${plan.accepted} reason=${plannerReason} elapsed=${Date.now() - planStartMs}ms rawLen=${plannerRawSnippet.length} raw=${JSON.stringify(plannerRawSnippet.slice(0, 300))}`;
225590
+ emit({ type: "diagnostic", code: "flock_planner_outcome", message: plannerTraceMsg, ts: now11() });
225591
+ void appendFlockTrace(`[${flockId}] ${plannerTraceMsg}`);
225548
225592
  emitPlanEvent(emit, plan);
225549
225593
  if (!plan.accepted) {
225550
225594
  emit({
@@ -225791,12 +225835,9 @@ ${FLOCK_GROUNDING_CONTRACT}` : worker.objective;
225791
225835
  buildFlockSynthesisPrompt(task, [...outcomes, ...revisionOutcomes], revisionReport),
225792
225836
  FLOCK_SYNTHESIS_TIMEOUT_MS
225793
225837
  );
225794
- emit({
225795
- type: "diagnostic",
225796
- code: "flock_merge_outcome",
225797
- message: `merge ${merge.reason} in ${merge.elapsedMs}ms`,
225798
- ts: now11()
225799
- });
225838
+ const mergeTraceMsg = `merge ${merge.reason} in ${merge.elapsedMs}ms`;
225839
+ emit({ type: "diagnostic", code: "flock_merge_outcome", message: mergeTraceMsg, ts: now11() });
225840
+ void appendFlockTrace(`[${plan.flockId}] ${mergeTraceMsg}`);
225800
225841
  if (merge.text) summaryBody = merge.text;
225801
225842
  }
225802
225843
  const assistantText = [
@@ -226161,6 +226202,21 @@ function flockWorkerStatusFromSpawnResult(result2) {
226161
226202
  function now11() {
226162
226203
  return (/* @__PURE__ */ new Date()).toISOString();
226163
226204
  }
226205
+ async function appendFlockTrace(line) {
226206
+ if (typeof window !== "undefined" || typeof process === "undefined") return;
226207
+ try {
226208
+ const [os9, path19, fs19] = await Promise.all([
226209
+ import("node:os"),
226210
+ import("node:path"),
226211
+ import("node:fs/promises")
226212
+ ]);
226213
+ const dir = path19.join(os9.homedir(), ".perch");
226214
+ await fs19.mkdir(dir, { recursive: true });
226215
+ await fs19.appendFile(path19.join(dir, "flock-trace.log"), `${now11()} ${line}
226216
+ `);
226217
+ } catch {
226218
+ }
226219
+ }
226164
226220
  var FLOCK_PLANNER_TIMEOUT_MS, FLOCK_WORKER_STALL_TIMEOUT_MS, FLOCK_SYNTHESIS_TIMEOUT_MS, FLOCK_SYNTHESIS_MAX_OUTPUT_PER_WORKER, FLOCK_GROUNDING_CONTRACT;
226165
226221
  var init_runFlockTurn = __esm({
226166
226222
  "features/perchTerminal/runtime/flock/runFlockTurn.ts"() {
@@ -226176,7 +226232,7 @@ var init_runFlockTurn = __esm({
226176
226232
  init_flockPlanner();
226177
226233
  init_flockRoles();
226178
226234
  init_toolLoop();
226179
- FLOCK_PLANNER_TIMEOUT_MS = 35e3;
226235
+ FLOCK_PLANNER_TIMEOUT_MS = 12e4;
226180
226236
  FLOCK_WORKER_STALL_TIMEOUT_MS = 15e4;
226181
226237
  FLOCK_SYNTHESIS_TIMEOUT_MS = 3e4;
226182
226238
  FLOCK_SYNTHESIS_MAX_OUTPUT_PER_WORKER = 8e3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.52",
3
+ "version": "2.4.54",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"