opencandle 0.10.0 → 0.11.1
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/README.md +12 -9
- package/dist/analysts/orchestrator.d.ts +3 -4
- package/dist/analysts/orchestrator.js +34 -44
- package/dist/analysts/orchestrator.js.map +1 -1
- package/dist/cli-main.js +242 -9
- package/dist/cli-main.js.map +1 -1
- package/dist/config.d.ts +4 -9
- package/dist/config.js +7 -10
- package/dist/config.js.map +1 -1
- package/dist/doctor/report.js +1 -1
- package/dist/doctor/report.js.map +1 -1
- package/dist/infra/cache.d.ts +6 -0
- package/dist/infra/cache.js +16 -6
- package/dist/infra/cache.js.map +1 -1
- package/dist/infra/freshness.d.ts +21 -0
- package/dist/infra/freshness.js +119 -0
- package/dist/infra/freshness.js.map +1 -0
- package/dist/infra/market-calendar.d.ts +14 -0
- package/dist/infra/market-calendar.js +137 -0
- package/dist/infra/market-calendar.js.map +1 -0
- package/dist/infra/rate-limiter.js +1 -0
- package/dist/infra/rate-limiter.js.map +1 -1
- package/dist/market-state/daily-report.d.ts +1 -1
- package/dist/market-state/daily-report.js +5 -16
- package/dist/market-state/daily-report.js.map +1 -1
- package/dist/market-state/service.d.ts +0 -35
- package/dist/market-state/service.js +0 -63
- package/dist/market-state/service.js.map +1 -1
- package/dist/market-state/summaries.d.ts +8 -0
- package/dist/market-state/summaries.js +70 -0
- package/dist/market-state/summaries.js.map +1 -0
- package/dist/memory/sqlite.js +20 -19
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/onboarding/providers.d.ts +25 -1
- package/dist/onboarding/providers.js +26 -0
- package/dist/onboarding/providers.js.map +1 -1
- package/dist/pi/opencandle-extension.js +57 -226
- package/dist/pi/opencandle-extension.js.map +1 -1
- package/dist/pi/session-action-dedupe.d.ts +6 -0
- package/dist/pi/session-action-dedupe.js +126 -0
- package/dist/pi/session-action-dedupe.js.map +1 -0
- package/dist/pi/session-writer-lock.d.ts +26 -2
- package/dist/pi/session-writer-lock.js +230 -18
- package/dist/pi/session-writer-lock.js.map +1 -1
- package/dist/pi/setup.js +5 -5
- package/dist/pi/setup.js.map +1 -1
- package/dist/pi/tui-session-coordinator.d.ts +15 -0
- package/dist/pi/tui-session-coordinator.js +283 -0
- package/dist/pi/tui-session-coordinator.js.map +1 -0
- package/dist/prompts/context-builder.js +1 -1
- package/dist/prompts/policy-cards.js +1 -1
- package/dist/prompts/policy-cards.js.map +1 -1
- package/dist/providers/alpha-vantage.js +6 -0
- package/dist/providers/alpha-vantage.js.map +1 -1
- package/dist/providers/coingecko.js +1 -0
- package/dist/providers/coingecko.js.map +1 -1
- package/dist/providers/polymarket.d.ts +2 -0
- package/dist/providers/polymarket.js +163 -0
- package/dist/providers/polymarket.js.map +1 -0
- package/dist/providers/wrap-provider.js +5 -3
- package/dist/providers/wrap-provider.js.map +1 -1
- package/dist/providers/yahoo-finance.d.ts +3 -0
- package/dist/providers/yahoo-finance.js +206 -10
- package/dist/providers/yahoo-finance.js.map +1 -1
- package/dist/routing/classify-intent.js +4 -5
- package/dist/routing/classify-intent.js.map +1 -1
- package/dist/routing/entity-extractor.js +16 -0
- package/dist/routing/entity-extractor.js.map +1 -1
- package/dist/routing/route-manifest.js +1 -2
- package/dist/routing/route-manifest.js.map +1 -1
- package/dist/routing/router-llm-client.js +18 -3
- package/dist/routing/router-llm-client.js.map +1 -1
- package/dist/routing/router-prompt.js +1 -1
- package/dist/routing/router.d.ts +1 -1
- package/dist/routing/router.js +309 -9
- package/dist/routing/router.js.map +1 -1
- package/dist/routing/slot-resolver.d.ts +1 -0
- package/dist/routing/slot-resolver.js +1 -1
- package/dist/routing/slot-resolver.js.map +1 -1
- package/dist/runtime/evidence.d.ts +1 -0
- package/dist/runtime/evidence.js.map +1 -1
- package/dist/runtime/numeric-claims.d.ts +23 -0
- package/dist/runtime/numeric-claims.js +100 -0
- package/dist/runtime/numeric-claims.js.map +1 -0
- package/dist/runtime/planning-evidence.js +1 -76
- package/dist/runtime/planning-evidence.js.map +1 -1
- package/dist/runtime/prompt-step.d.ts +10 -1
- package/dist/runtime/prompt-step.js +116 -2
- package/dist/runtime/prompt-step.js.map +1 -1
- package/dist/runtime/session-coordinator.d.ts +11 -1
- package/dist/runtime/session-coordinator.js +354 -62
- package/dist/runtime/session-coordinator.js.map +1 -1
- package/dist/runtime/validation.d.ts +3 -1
- package/dist/runtime/workflow-events.d.ts +1 -1
- package/dist/runtime/workflow-events.js.map +1 -1
- package/dist/runtime/workflow-types.d.ts +3 -0
- package/dist/runtime/workflow-types.js.map +1 -1
- package/dist/system-prompt.js +1 -1
- package/dist/tools/fundamentals/comps.d.ts +1 -0
- package/dist/tools/fundamentals/comps.js +20 -9
- package/dist/tools/fundamentals/comps.js.map +1 -1
- package/dist/tools/fundamentals/dcf.d.ts +1 -1
- package/dist/tools/fundamentals/dcf.js +190 -76
- package/dist/tools/fundamentals/dcf.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +3 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/macro/event-probabilities.d.ts +8 -0
- package/dist/tools/macro/event-probabilities.js +121 -0
- package/dist/tools/macro/event-probabilities.js.map +1 -0
- package/dist/tools/market/crypto-price.d.ts +4 -1
- package/dist/tools/market/crypto-price.js +10 -1
- package/dist/tools/market/crypto-price.js.map +1 -1
- package/dist/tools/market/screen-stocks.js +14 -3
- package/dist/tools/market/screen-stocks.js.map +1 -1
- package/dist/tools/market/stock-quote.d.ts +4 -1
- package/dist/tools/market/stock-quote.js +9 -4
- package/dist/tools/market/stock-quote.js.map +1 -1
- package/dist/tools/options/option-chain.d.ts +4 -1
- package/dist/tools/options/option-chain.js +12 -1
- package/dist/tools/options/option-chain.js.map +1 -1
- package/dist/tools/portfolio/daily-report.js +10 -4
- package/dist/tools/portfolio/daily-report.js.map +1 -1
- package/dist/tools/portfolio/risk-analysis.js +1 -1
- package/dist/tools/portfolio/risk-analysis.js.map +1 -1
- package/dist/tools/technical/backtest.d.ts +23 -5
- package/dist/tools/technical/backtest.js +131 -94
- package/dist/tools/technical/backtest.js.map +1 -1
- package/dist/tools/technical/indicators.js +1 -1
- package/dist/tools/technical/indicators.js.map +1 -1
- package/dist/types/fundamentals.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/market.d.ts +2 -0
- package/dist/types/options.d.ts +1 -0
- package/dist/types/prediction-markets.d.ts +13 -0
- package/dist/types/prediction-markets.js +2 -0
- package/dist/types/prediction-markets.js.map +1 -0
- package/gui/server/chat-event-adapter.ts +89 -5
- package/gui/server/http-routes.ts +661 -37
- package/gui/server/invoke-tool.ts +165 -16
- package/gui/server/live-chat-event-adapter.ts +37 -2
- package/gui/server/local-session-coordinator.ts +97 -0
- package/gui/server/market-state-api.ts +64 -48
- package/gui/server/projector.ts +132 -3
- package/gui/server/server.ts +51 -6
- package/gui/server/session-actions.ts +146 -45
- package/gui/server/session-entry-wait.ts +22 -3
- package/gui/server/tool-metadata.ts +3 -1
- package/gui/server/ws-hub.ts +77 -10
- package/gui/shared/chat-events.ts +10 -1
- package/gui/shared/event-reducer.ts +1 -0
- package/gui/web/dist/assets/CatalogOverlay-DZ1niyQm.js +1 -0
- package/gui/web/dist/assets/index-D4F9AJnn.css +2 -0
- package/gui/web/dist/assets/index-DtqMMBTr.js +65 -0
- package/gui/web/dist/index.html +2 -2
- package/package.json +13 -15
- package/src/analysts/orchestrator.ts +35 -56
- package/src/cli-main.ts +253 -13
- package/src/config.ts +12 -20
- package/src/doctor/report.ts +1 -1
- package/src/infra/cache.ts +24 -11
- package/src/infra/freshness.ts +165 -0
- package/src/infra/market-calendar.ts +193 -0
- package/src/infra/rate-limiter.ts +1 -0
- package/src/market-state/daily-report.ts +6 -16
- package/src/market-state/service.ts +0 -136
- package/src/market-state/summaries.ts +75 -0
- package/src/memory/sqlite.ts +23 -19
- package/src/onboarding/providers.ts +29 -1
- package/src/pi/opencandle-extension.ts +67 -270
- package/src/pi/session-action-dedupe.ts +155 -0
- package/src/pi/session-writer-lock.ts +290 -20
- package/src/pi/setup.ts +6 -6
- package/src/pi/tui-session-coordinator.ts +351 -0
- package/src/prompts/context-builder.ts +1 -1
- package/src/prompts/policy-cards.ts +1 -1
- package/src/providers/alpha-vantage.ts +6 -0
- package/src/providers/coingecko.ts +2 -0
- package/src/providers/polymarket.ts +214 -0
- package/src/providers/wrap-provider.ts +5 -3
- package/src/providers/yahoo-finance.ts +339 -27
- package/src/routing/classify-intent.ts +4 -5
- package/src/routing/entity-extractor.ts +17 -0
- package/src/routing/route-manifest.ts +1 -2
- package/src/routing/router-llm-client.ts +31 -19
- package/src/routing/router-prompt.ts +1 -1
- package/src/routing/router.ts +379 -8
- package/src/routing/slot-resolver.ts +1 -1
- package/src/runtime/evidence.ts +1 -0
- package/src/runtime/numeric-claims.ts +108 -0
- package/src/runtime/planning-evidence.ts +6 -91
- package/src/runtime/prompt-step.ts +127 -2
- package/src/runtime/session-coordinator.ts +464 -74
- package/src/runtime/validation.ts +1 -1
- package/src/runtime/workflow-events.ts +2 -0
- package/src/runtime/workflow-types.ts +3 -0
- package/src/system-prompt.ts +1 -1
- package/src/tools/AGENTS.md +1 -1
- package/src/tools/fundamentals/comps.ts +25 -14
- package/src/tools/fundamentals/dcf.ts +217 -87
- package/src/tools/index.ts +3 -3
- package/src/tools/macro/event-probabilities.ts +141 -0
- package/src/tools/market/crypto-price.ts +14 -2
- package/src/tools/market/screen-stocks.ts +14 -3
- package/src/tools/market/stock-quote.ts +49 -43
- package/src/tools/options/option-chain.ts +16 -2
- package/src/tools/portfolio/daily-report.ts +10 -4
- package/src/tools/portfolio/risk-analysis.ts +1 -1
- package/src/tools/technical/backtest.ts +167 -108
- package/src/tools/technical/indicators.ts +1 -1
- package/src/types/fundamentals.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/types/market.ts +2 -0
- package/src/types/options.ts +1 -0
- package/src/types/prediction-markets.ts +13 -0
- package/dist/tools/portfolio/predictions.d.ts +0 -55
- package/dist/tools/portfolio/predictions.js +0 -422
- package/dist/tools/portfolio/predictions.js.map +0 -1
- package/gui/server/chat-run-session.ts +0 -16
- package/gui/web/dist/assets/CatalogOverlay-CYptsda-.js +0 -1
- package/gui/web/dist/assets/index-B7QAjY5g.js +0 -65
- package/gui/web/dist/assets/index-D5dbWPfM.css +0 -2
- package/src/tools/portfolio/predictions.ts +0 -553
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
classifyMarketStatus,
|
|
3
|
+
KNOWN_US_MARKET_HOLIDAYS,
|
|
4
|
+
lastTradingDay,
|
|
5
|
+
localDateTimeParts,
|
|
6
|
+
} from "../infra/market-calendar.js";
|
|
1
7
|
import type { ParsedTag } from "../onboarding/tool-tags.js";
|
|
2
8
|
import { parseToolTag } from "../onboarding/tool-tags.js";
|
|
3
9
|
import type { CapabilityGapId, EvidencePlanId, TaskFamily } from "../routing/planning.js";
|
|
@@ -202,19 +208,6 @@ export const EVIDENCE_PLAN_REGISTRY: Record<EvidencePlanId, EvidencePlanDefiniti
|
|
|
202
208
|
),
|
|
203
209
|
};
|
|
204
210
|
|
|
205
|
-
const KNOWN_US_MARKET_HOLIDAYS: Record<string, string> = {
|
|
206
|
-
"2026-01-01": "New Year's Day",
|
|
207
|
-
"2026-01-19": "Martin Luther King Jr. Day",
|
|
208
|
-
"2026-02-16": "Washington's Birthday",
|
|
209
|
-
"2026-04-03": "Good Friday",
|
|
210
|
-
"2026-05-25": "Memorial Day",
|
|
211
|
-
"2026-06-19": "Juneteenth",
|
|
212
|
-
"2026-07-03": "Independence Day observed",
|
|
213
|
-
"2026-09-07": "Labor Day",
|
|
214
|
-
"2026-11-26": "Thanksgiving Day",
|
|
215
|
-
"2026-12-25": "Christmas Day",
|
|
216
|
-
};
|
|
217
|
-
|
|
218
211
|
function placeholderPlan(
|
|
219
212
|
id: EvidencePlanId,
|
|
220
213
|
taskFamilies: TaskFamily[],
|
|
@@ -591,20 +584,6 @@ function temporalReferencesFor(text: string): string[] {
|
|
|
591
584
|
return refs;
|
|
592
585
|
}
|
|
593
586
|
|
|
594
|
-
function classifyMarketStatus(
|
|
595
|
-
local: LocalDateTimeParts,
|
|
596
|
-
isWeekend: boolean,
|
|
597
|
-
isMarketHoliday: boolean,
|
|
598
|
-
temporalReferences: string[],
|
|
599
|
-
): string {
|
|
600
|
-
if (isWeekend) return "closed_weekend";
|
|
601
|
-
if (isMarketHoliday) return "closed_holiday";
|
|
602
|
-
if (local.minutesSinceMidnight < 9 * 60 + 30) return "pre_market";
|
|
603
|
-
if (local.minutesSinceMidnight < 16 * 60) return "open";
|
|
604
|
-
if (temporalReferences.includes("after_close")) return "after_close";
|
|
605
|
-
return "closed_after_hours";
|
|
606
|
-
}
|
|
607
|
-
|
|
608
587
|
function quoteAsOfCaveat(marketStatus: string): string {
|
|
609
588
|
if (marketStatus === "open")
|
|
610
589
|
return "Quote evidence may be intraday or delayed depending on provider.";
|
|
@@ -613,70 +592,6 @@ function quoteAsOfCaveat(marketStatus: string): string {
|
|
|
613
592
|
return "Quote evidence should distinguish the current calendar date from the most recent trading session.";
|
|
614
593
|
}
|
|
615
594
|
|
|
616
|
-
interface LocalDateTimeParts {
|
|
617
|
-
date: string;
|
|
618
|
-
time: string;
|
|
619
|
-
weekday: string;
|
|
620
|
-
minutesSinceMidnight: number;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
function localDateTimeParts(date: Date, timezone: string): LocalDateTimeParts {
|
|
624
|
-
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
625
|
-
timeZone: timezone,
|
|
626
|
-
year: "numeric",
|
|
627
|
-
month: "2-digit",
|
|
628
|
-
day: "2-digit",
|
|
629
|
-
hour: "2-digit",
|
|
630
|
-
minute: "2-digit",
|
|
631
|
-
hour12: false,
|
|
632
|
-
weekday: "short",
|
|
633
|
-
});
|
|
634
|
-
const parts = formatter.formatToParts(date).reduce<Record<string, string>>((acc, part) => {
|
|
635
|
-
acc[part.type] = part.value;
|
|
636
|
-
return acc;
|
|
637
|
-
}, {});
|
|
638
|
-
const hour = Number(parts.hour);
|
|
639
|
-
const minute = Number(parts.minute);
|
|
640
|
-
return {
|
|
641
|
-
date: `${parts.year}-${parts.month}-${parts.day}`,
|
|
642
|
-
time: `${parts.hour}:${parts.minute}`,
|
|
643
|
-
weekday: parts.weekday ?? "",
|
|
644
|
-
minutesSinceMidnight: hour * 60 + minute,
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
function lastTradingDay(localDate: string): string {
|
|
649
|
-
let cursor = dateFromKey(localDate);
|
|
650
|
-
do {
|
|
651
|
-
cursor = addDays(cursor, -1);
|
|
652
|
-
} while (isWeekendOrKnownHoliday(dateKey(cursor)));
|
|
653
|
-
return dateKey(cursor);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
function isWeekendOrKnownHoliday(key: string): boolean {
|
|
657
|
-
const date = dateFromKey(key);
|
|
658
|
-
const day = date.getUTCDay();
|
|
659
|
-
return day === 0 || day === 6 || KNOWN_US_MARKET_HOLIDAYS[key] !== undefined;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function dateFromKey(key: string): Date {
|
|
663
|
-
const [year, month, day] = key.split("-").map(Number);
|
|
664
|
-
return new Date(Date.UTC(year, month - 1, day));
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
function addDays(date: Date, days: number): Date {
|
|
668
|
-
const next = new Date(date);
|
|
669
|
-
next.setUTCDate(next.getUTCDate() + days);
|
|
670
|
-
return next;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
function dateKey(date: Date): string {
|
|
674
|
-
const year = date.getUTCFullYear();
|
|
675
|
-
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
676
|
-
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
677
|
-
return `${year}-${month}-${day}`;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
595
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
681
596
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
682
597
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { FreshnessStamp } from "../infra/freshness.js";
|
|
3
|
+
import type { EvidenceRecord } from "./evidence.js";
|
|
1
4
|
import type { StepOutput, WorkflowStep } from "./workflow-types.js";
|
|
2
5
|
|
|
3
6
|
/**
|
|
@@ -43,14 +46,98 @@ export function promptStep(
|
|
|
43
46
|
* Create a StepOutput for a prompt-based step (no structured evidence yet).
|
|
44
47
|
* Evidence will be captured separately via tool call hooks.
|
|
45
48
|
*/
|
|
46
|
-
export function promptStepOutput(
|
|
49
|
+
export function promptStepOutput(
|
|
50
|
+
stepIndex: number,
|
|
51
|
+
stepType: string,
|
|
52
|
+
options: { evidence?: EvidenceRecord[]; rawText?: string } = {},
|
|
53
|
+
): StepOutput {
|
|
47
54
|
return {
|
|
48
55
|
stepIndex,
|
|
49
56
|
stepType,
|
|
50
|
-
evidence: [],
|
|
57
|
+
evidence: options.evidence ?? [],
|
|
58
|
+
...(options.rawText ? { rawText: options.rawText } : {}),
|
|
51
59
|
};
|
|
52
60
|
}
|
|
53
61
|
|
|
62
|
+
/** Capture compact evidence records from session entries produced by one step. */
|
|
63
|
+
export function captureToolEvidence(entries: SessionEntry[]): EvidenceRecord[] {
|
|
64
|
+
const calls = new Map<string, { tool: string; args: unknown; startedAt: string }>();
|
|
65
|
+
const evidence: EvidenceRecord[] = [];
|
|
66
|
+
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
if (entry.type !== "message") continue;
|
|
69
|
+
const message = entry.message as unknown as Record<string, unknown>;
|
|
70
|
+
|
|
71
|
+
if (message.role === "assistant") {
|
|
72
|
+
for (const part of Array.isArray(message.content) ? message.content : []) {
|
|
73
|
+
const record = asRecord(part);
|
|
74
|
+
if (record.type !== "toolCall") continue;
|
|
75
|
+
const id = stringValue(record.id);
|
|
76
|
+
const tool = stringValue(record.name);
|
|
77
|
+
if (!id || !tool) continue;
|
|
78
|
+
calls.set(id, {
|
|
79
|
+
tool,
|
|
80
|
+
args: record.arguments ?? record.args ?? {},
|
|
81
|
+
startedAt: entry.timestamp,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (message.role !== "toolResult") continue;
|
|
88
|
+
const toolCallId = stringValue(message.toolCallId);
|
|
89
|
+
const pending = toolCallId ? calls.get(toolCallId) : undefined;
|
|
90
|
+
const tool = pending?.tool ?? stringValue(message.toolName);
|
|
91
|
+
if (!tool) continue;
|
|
92
|
+
const resultValue = message.details ?? message.content ?? "";
|
|
93
|
+
const freshness = extractFreshness(resultValue);
|
|
94
|
+
const serializedResult = serialize(resultValue);
|
|
95
|
+
evidence.push({
|
|
96
|
+
label: `tool:${tool}`,
|
|
97
|
+
value: {
|
|
98
|
+
tool,
|
|
99
|
+
args: truncate(serialize(pending?.args ?? {}), 500),
|
|
100
|
+
...(freshness ? { freshness } : {}),
|
|
101
|
+
resultDigest: {
|
|
102
|
+
preview: truncate(serializedResult, 500),
|
|
103
|
+
totalLength: serializedResult.length,
|
|
104
|
+
},
|
|
105
|
+
startedAt: pending?.startedAt ?? entry.timestamp,
|
|
106
|
+
completedAt: entry.timestamp,
|
|
107
|
+
},
|
|
108
|
+
provenance: {
|
|
109
|
+
source: "computed",
|
|
110
|
+
timestamp: freshness?.providerDataAt ?? freshness?.fetchedAt ?? entry.timestamp,
|
|
111
|
+
provider: tool,
|
|
112
|
+
confidence: message.isError === true ? 0.5 : undefined,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return evidence;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Extract assistant text emitted during a step, preserving final response order. */
|
|
121
|
+
export function extractAssistantText(entries: SessionEntry[]): string {
|
|
122
|
+
return entries
|
|
123
|
+
.filter((entry) => entry.type === "message")
|
|
124
|
+
.flatMap((entry) => {
|
|
125
|
+
const message = (entry as Extract<SessionEntry, { type: "message" }>)
|
|
126
|
+
.message as unknown as Record<string, unknown>;
|
|
127
|
+
if (message.role !== "assistant") return [];
|
|
128
|
+
const content = message.content;
|
|
129
|
+
if (typeof content === "string") return [content];
|
|
130
|
+
if (!Array.isArray(content)) return [];
|
|
131
|
+
return content
|
|
132
|
+
.map((part) => asRecord(part))
|
|
133
|
+
.filter((part) => part.type === "text")
|
|
134
|
+
.map((part) => stringValue(part.text) ?? "")
|
|
135
|
+
.filter(Boolean);
|
|
136
|
+
})
|
|
137
|
+
.join("\n")
|
|
138
|
+
.trim();
|
|
139
|
+
}
|
|
140
|
+
|
|
54
141
|
/**
|
|
55
142
|
* Extract just the WorkflowStep metadata from PromptStep definitions
|
|
56
143
|
* (dropping the prompt field) for passing to WorkflowRunner.
|
|
@@ -58,3 +145,41 @@ export function promptStepOutput(stepIndex: number, stepType: string): StepOutpu
|
|
|
58
145
|
export function toStepDefinitions(steps: PromptStep[]): Omit<WorkflowStep, "status">[] {
|
|
59
146
|
return steps.map(({ prompt: _prompt, ...step }) => step);
|
|
60
147
|
}
|
|
148
|
+
|
|
149
|
+
function serialize(value: unknown): string {
|
|
150
|
+
if (typeof value === "string") return value;
|
|
151
|
+
try {
|
|
152
|
+
return JSON.stringify(value);
|
|
153
|
+
} catch {
|
|
154
|
+
return String(value);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function truncate(value: string, maxLength: number): string {
|
|
159
|
+
return value.length > maxLength ? value.slice(0, maxLength) : value;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function asRecord(value: unknown): Record<string, unknown> {
|
|
163
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
164
|
+
? (value as Record<string, unknown>)
|
|
165
|
+
: {};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function stringValue(value: unknown): string | undefined {
|
|
169
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function extractFreshness(value: unknown): FreshnessStamp | undefined {
|
|
173
|
+
const record = asRecord(value);
|
|
174
|
+
return isFreshnessStamp(record.freshness) ? record.freshness : undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isFreshnessStamp(value: unknown): value is FreshnessStamp {
|
|
178
|
+
const record = asRecord(value);
|
|
179
|
+
return (
|
|
180
|
+
typeof record.fetchedAt === "string" &&
|
|
181
|
+
typeof record.cacheStatus === "string" &&
|
|
182
|
+
typeof record.marketSession === "string" &&
|
|
183
|
+
typeof record.isStaleForSession === "boolean"
|
|
184
|
+
);
|
|
185
|
+
}
|