perchai-cli 2.4.52 → 2.4.53

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 +90 -38
  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
  });
@@ -84012,6 +84014,7 @@ function listWorkerContracts() {
84012
84014
  }
84013
84015
  var init_workerManifest = __esm({
84014
84016
  "features/perchTerminal/runtime/workers/workerManifest.ts"() {
84017
+ "use strict";
84015
84018
  init_managedWorkflowRegistry();
84016
84019
  init_platformRoles();
84017
84020
  init_financialRoles();
@@ -87169,7 +87172,6 @@ function truncateHistoryLine(value, max2) {
87169
87172
  }
87170
87173
  var init_operatorTruth = __esm({
87171
87174
  "features/perchTerminal/runtime/operatorTruth.ts"() {
87172
- "use strict";
87173
87175
  }
87174
87176
  });
87175
87177
 
@@ -92399,7 +92401,6 @@ function listFinancialPlaybooks() {
92399
92401
  var AP_AUDIT_PACKET_DEF, PLAYBOOKS;
92400
92402
  var init_registry2 = __esm({
92401
92403
  "features/perchTerminal/runtime/financialPlaybooks/registry.ts"() {
92402
- "use strict";
92403
92404
  init_managedWorkflowRegistry2();
92404
92405
  init_toolNames();
92405
92406
  AP_AUDIT_PACKET_DEF = {
@@ -199475,7 +199476,6 @@ function recordDispatchBatchResult(tasks, result2, ctx, opts = {}) {
199475
199476
  var lifecycleByRun, MAX_LIFECYCLE_RUNS;
199476
199477
  var init_workerLifecycle = __esm({
199477
199478
  "features/perchTerminal/runtime/workers/workerLifecycle.ts"() {
199478
- "use strict";
199479
199479
  init_workerManifest();
199480
199480
  lifecycleByRun = /* @__PURE__ */ new Map();
199481
199481
  MAX_LIFECYCLE_RUNS = 200;
@@ -200020,7 +200020,6 @@ function dedupeEvidence(items) {
200020
200020
  var packetStore, ROLE_KIND_MAP, DOWNSTREAM_CONSUMERS, URL_PATTERN, MARKDOWN_LINK_PATTERN;
200021
200021
  var init_contextPackets = __esm({
200022
200022
  "features/perchTerminal/agentPlatform/contextPackets.ts"() {
200023
- "use strict";
200024
200023
  packetStore = /* @__PURE__ */ new Map();
200025
200024
  ROLE_KIND_MAP = {
200026
200025
  legal_source_scout: "research",
@@ -210204,25 +210203,61 @@ var init_workGraph = __esm({
210204
210203
  });
210205
210204
 
210206
210205
  // 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;
210206
+ function stripReasoningWrappers(text) {
210207
+ 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, " ");
210208
+ }
210209
+ function balancedJsonObjects(text) {
210210
+ const out = [];
210211
+ let depth = 0;
210212
+ let start = -1;
210213
+ let inString = false;
210214
+ let escaped = false;
210215
+ for (let i = 0; i < text.length; i++) {
210216
+ const ch = text[i];
210217
+ if (inString) {
210218
+ if (escaped) escaped = false;
210219
+ else if (ch === "\\") escaped = true;
210220
+ else if (ch === '"') inString = false;
210221
+ continue;
210222
+ }
210223
+ if (ch === '"') {
210224
+ inString = true;
210225
+ } else if (ch === "{") {
210226
+ if (depth === 0) start = i;
210227
+ depth++;
210228
+ } else if (ch === "}" && depth > 0) {
210229
+ depth--;
210230
+ if (depth === 0 && start >= 0) {
210231
+ out.push(text.slice(start, i + 1));
210232
+ start = -1;
210233
+ }
210234
+ }
210235
+ }
210236
+ return out;
210237
+ }
210238
+ function jsonCandidates(text) {
210239
+ const candidates = [];
210240
+ const stripped = stripReasoningWrappers(text).trim();
210241
+ if (!stripped) return candidates;
210242
+ const fenceMatch = stripped.match(/```(?:json)?\s*\n?([\s\S]*?)```/i);
210243
+ if (fenceMatch?.[1]?.trim()) candidates.push(fenceMatch[1].trim());
210244
+ if (stripped.startsWith("{") || stripped.startsWith("[")) candidates.push(stripped);
210245
+ for (const obj2 of balancedJsonObjects(stripped).sort((a, b2) => b2.length - a.length)) {
210246
+ candidates.push(obj2);
210247
+ }
210248
+ const greedy = stripped.match(/\{[\s\S]*\}|\[[\s\S]*\]/);
210249
+ if (greedy?.[0]) candidates.push(greedy[0]);
210250
+ return candidates;
210216
210251
  }
210217
210252
  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;
210253
+ for (const candidate of jsonCandidates(text)) {
210254
+ try {
210255
+ const parsed = JSON.parse(candidate);
210256
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
210257
+ return parsed;
210258
+ }
210259
+ } catch {
210224
210260
  }
210225
- } catch {
210226
210261
  }
210227
210262
  return null;
210228
210263
  }
@@ -225499,6 +225534,8 @@ async function runFlockTurn(input, deps, options = {}) {
225499
225534
  ensureFlockWorkersRegistered();
225500
225535
  const planStartMs = Date.now();
225501
225536
  let plan = null;
225537
+ let plannerRawSnippet = "";
225538
+ let plannerTimedOut = false;
225502
225539
  if (options.plannerModelCall !== null) {
225503
225540
  const llmCtx = {
225504
225541
  task,
@@ -225506,13 +225543,20 @@ async function runFlockTurn(input, deps, options = {}) {
225506
225543
  surface: detectFlockSurface(),
225507
225544
  turnInput: input
225508
225545
  };
225509
- const modelCall = options.plannerModelCall ?? defaultFlockPlannerModelCall(llmCtx);
225546
+ const baseModelCall = options.plannerModelCall ?? defaultFlockPlannerModelCall(llmCtx);
225547
+ const modelCall = async (prompts) => {
225548
+ const result2 = await baseModelCall(prompts);
225549
+ plannerRawSnippet = (result2.text ?? "").trim().slice(0, 600);
225550
+ return result2;
225551
+ };
225510
225552
  const plannerTimeoutMs = options.plannerTimeoutMs ?? FLOCK_PLANNER_TIMEOUT_MS;
225511
225553
  const first2 = await runLlmPlannerWithTimeout(llmCtx, modelCall, plannerTimeoutMs);
225512
225554
  plan = first2.plan;
225555
+ plannerTimedOut = first2.timedOut;
225513
225556
  if (!plan && !first2.timedOut) {
225514
225557
  const retry = await runLlmPlannerWithTimeout(llmCtx, modelCall, plannerTimeoutMs);
225515
225558
  plan = retry.plan;
225559
+ plannerTimedOut = retry.timedOut;
225516
225560
  }
225517
225561
  }
225518
225562
  if (!plan) {
@@ -225539,12 +225583,10 @@ async function runFlockTurn(input, deps, options = {}) {
225539
225583
  );
225540
225584
  }
225541
225585
  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
- });
225586
+ const plannerReason = plannerTimedOut ? "timeout" : plan.accepted ? "ok" : plannerRawSnippet ? "unparseable_or_invalid" : "empty_or_error";
225587
+ 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))}`;
225588
+ emit({ type: "diagnostic", code: "flock_planner_outcome", message: plannerTraceMsg, ts: now11() });
225589
+ void appendFlockTrace(`[${flockId}] ${plannerTraceMsg}`);
225548
225590
  emitPlanEvent(emit, plan);
225549
225591
  if (!plan.accepted) {
225550
225592
  emit({
@@ -225791,12 +225833,9 @@ ${FLOCK_GROUNDING_CONTRACT}` : worker.objective;
225791
225833
  buildFlockSynthesisPrompt(task, [...outcomes, ...revisionOutcomes], revisionReport),
225792
225834
  FLOCK_SYNTHESIS_TIMEOUT_MS
225793
225835
  );
225794
- emit({
225795
- type: "diagnostic",
225796
- code: "flock_merge_outcome",
225797
- message: `merge ${merge.reason} in ${merge.elapsedMs}ms`,
225798
- ts: now11()
225799
- });
225836
+ const mergeTraceMsg = `merge ${merge.reason} in ${merge.elapsedMs}ms`;
225837
+ emit({ type: "diagnostic", code: "flock_merge_outcome", message: mergeTraceMsg, ts: now11() });
225838
+ void appendFlockTrace(`[${plan.flockId}] ${mergeTraceMsg}`);
225800
225839
  if (merge.text) summaryBody = merge.text;
225801
225840
  }
225802
225841
  const assistantText = [
@@ -226161,6 +226200,21 @@ function flockWorkerStatusFromSpawnResult(result2) {
226161
226200
  function now11() {
226162
226201
  return (/* @__PURE__ */ new Date()).toISOString();
226163
226202
  }
226203
+ async function appendFlockTrace(line) {
226204
+ if (typeof window !== "undefined" || typeof process === "undefined") return;
226205
+ try {
226206
+ const [os9, path19, fs19] = await Promise.all([
226207
+ import("node:os"),
226208
+ import("node:path"),
226209
+ import("node:fs/promises")
226210
+ ]);
226211
+ const dir = path19.join(os9.homedir(), ".perch");
226212
+ await fs19.mkdir(dir, { recursive: true });
226213
+ await fs19.appendFile(path19.join(dir, "flock-trace.log"), `${now11()} ${line}
226214
+ `);
226215
+ } catch {
226216
+ }
226217
+ }
226164
226218
  var FLOCK_PLANNER_TIMEOUT_MS, FLOCK_WORKER_STALL_TIMEOUT_MS, FLOCK_SYNTHESIS_TIMEOUT_MS, FLOCK_SYNTHESIS_MAX_OUTPUT_PER_WORKER, FLOCK_GROUNDING_CONTRACT;
226165
226219
  var init_runFlockTurn = __esm({
226166
226220
  "features/perchTerminal/runtime/flock/runFlockTurn.ts"() {
@@ -234592,15 +234646,13 @@ function getBackgroundTaskStore() {
234592
234646
  var STORE_FILE, BackgroundTaskStore, singleton;
234593
234647
  var init_backgroundTaskRegistry = __esm({
234594
234648
  "features/perchTerminal/runtime/background/backgroundTaskRegistry.ts"() {
234649
+ "use strict";
234595
234650
  init_backgroundTaskTypes();
234596
234651
  STORE_FILE = "background-tasks.json";
234597
234652
  BackgroundTaskStore = class {
234598
- baseDir;
234599
- storePath;
234600
- outputDir;
234601
- records = /* @__PURE__ */ new Map();
234602
- loaded = false;
234603
234653
  constructor(options = {}) {
234654
+ this.records = /* @__PURE__ */ new Map();
234655
+ this.loaded = false;
234604
234656
  this.baseDir = options.baseDir ?? path11.join(os.homedir(), ".perch");
234605
234657
  this.storePath = path11.join(this.baseDir, STORE_FILE);
234606
234658
  this.outputDir = path11.join(this.baseDir, "background-output");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.52",
3
+ "version": "2.4.53",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"