@matheuskrumenauer/tanya 0.17.0 → 0.17.6
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/{chunk-5PSV2Y3X.js → chunk-3NV2QP7J.js} +576 -249
- package/dist/chunk-3NV2QP7J.js.map +1 -0
- package/dist/cli.js +91 -5
- package/dist/cli.js.map +1 -1
- package/dist/{runInkChat-AZFI7553.js → runInkChat-SVBEQCQ4.js} +76 -9
- package/dist/runInkChat-SVBEQCQ4.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-5PSV2Y3X.js.map +0 -1
- package/dist/runInkChat-AZFI7553.js.map +0 -1
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
sessionToInkMessages,
|
|
14
14
|
startChatSession,
|
|
15
15
|
statsToInkStats
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3NV2QP7J.js";
|
|
17
17
|
|
|
18
18
|
// src/ui/ink/runInkChat.tsx
|
|
19
19
|
import { render } from "ink";
|
|
@@ -22,6 +22,14 @@ import { render } from "ink";
|
|
|
22
22
|
import { useEffect as useEffect2, useReducer, useRef as useRef2 } from "react";
|
|
23
23
|
import { Box as Box7, useApp } from "ink";
|
|
24
24
|
|
|
25
|
+
// src/agent/compression.ts
|
|
26
|
+
function estimateTokens(messages) {
|
|
27
|
+
return messages.reduce((sum, msg) => {
|
|
28
|
+
const text = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content ?? "");
|
|
29
|
+
return sum + Math.ceil(text.length / 4);
|
|
30
|
+
}, 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
// src/ui/ink/Footer.tsx
|
|
26
34
|
import { Box, Text } from "ink";
|
|
27
35
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -37,11 +45,22 @@ function formatFooterCost(costUsd) {
|
|
|
37
45
|
if (costUsd === 0) return "$0.00";
|
|
38
46
|
return formatUsd(costUsd);
|
|
39
47
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
48
|
+
function inflightTokenTotal(inflight) {
|
|
49
|
+
if (!inflight) return 0;
|
|
50
|
+
return inflight.promptTokens + inflight.completionTokens + inflight.reasoningTokens;
|
|
51
|
+
}
|
|
52
|
+
function Footer({ provider, model, sessionStartMs, stats, inflight, now, showColdStartHint = false }) {
|
|
53
|
+
const inflightTokens = inflightTokenTotal(inflight);
|
|
54
|
+
const inflightCost = inflight?.costUsd ?? 0;
|
|
55
|
+
const baseCost = stats.costUsd ?? 0;
|
|
56
|
+
const liveCost = inflightTokens > 0 || inflightCost > 0 ? baseCost + inflightCost : stats.costUsd;
|
|
57
|
+
const baseTokens = stats.totalTokens ?? 0;
|
|
58
|
+
const liveTokens = inflightTokens > 0 ? baseTokens + inflightTokens : stats.totalTokens;
|
|
59
|
+
const livePrefix = inflightTokens > 0 ? "~" : "";
|
|
60
|
+
const cost = formatFooterCost(liveCost);
|
|
42
61
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
43
62
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: divider }),
|
|
44
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: showColdStartHint ? "First turn may take ~30-60s on DeepSeek V4-Pro (cold-start + skill loading)." : `${provider}:${model} \xB7 session ${formatElapsed(now - sessionStartMs)} \xB7 ${cost} \xB7 ${formatTokens(
|
|
63
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: showColdStartHint ? "First turn may take ~30-60s on DeepSeek V4-Pro (cold-start + skill loading)." : `${provider}:${model} \xB7 session ${formatElapsed(now - sessionStartMs)} \xB7 ${livePrefix}${cost} \xB7 ${livePrefix}${formatTokens(liveTokens)} \xB7 /help` })
|
|
45
64
|
] });
|
|
46
65
|
}
|
|
47
66
|
|
|
@@ -325,8 +344,19 @@ function createInkSink(dispatch, options) {
|
|
|
325
344
|
let reasoningFlushHandle = null;
|
|
326
345
|
let reasoningStartedAt = null;
|
|
327
346
|
let streamedTokenChars = 0;
|
|
347
|
+
let streamedReasoningChars = 0;
|
|
348
|
+
let lastProgressCompletionTokens = 0;
|
|
349
|
+
let lastProgressReasoningTokens = 0;
|
|
328
350
|
let toolCount = 0;
|
|
329
351
|
const flushIntervalMs = options.flushIntervalMs ?? 30;
|
|
352
|
+
const dispatchProgressEstimate = () => {
|
|
353
|
+
const completionTokens = Math.ceil(streamedTokenChars / 4);
|
|
354
|
+
const reasoningTokens = Math.ceil(streamedReasoningChars / 4);
|
|
355
|
+
if (completionTokens === lastProgressCompletionTokens && reasoningTokens === lastProgressReasoningTokens) return;
|
|
356
|
+
lastProgressCompletionTokens = completionTokens;
|
|
357
|
+
lastProgressReasoningTokens = reasoningTokens;
|
|
358
|
+
dispatch({ type: "turn_progress", completionTokens, reasoningTokens });
|
|
359
|
+
};
|
|
330
360
|
const ensureAssistant = () => {
|
|
331
361
|
if (assistantId) return assistantId;
|
|
332
362
|
const timestampMs = Date.now();
|
|
@@ -397,6 +427,7 @@ function createInkSink(dispatch, options) {
|
|
|
397
427
|
ensureAssistant();
|
|
398
428
|
buffer += event.text;
|
|
399
429
|
streamedTokenChars += event.text.length;
|
|
430
|
+
dispatchProgressEstimate();
|
|
400
431
|
scheduleFlush();
|
|
401
432
|
break;
|
|
402
433
|
}
|
|
@@ -405,6 +436,8 @@ function createInkSink(dispatch, options) {
|
|
|
405
436
|
break;
|
|
406
437
|
case "reasoning_chunk":
|
|
407
438
|
reasoningBuffer += event.content;
|
|
439
|
+
streamedReasoningChars += event.content.length;
|
|
440
|
+
dispatchProgressEstimate();
|
|
408
441
|
scheduleReasoningFlush();
|
|
409
442
|
break;
|
|
410
443
|
case "tool_call": {
|
|
@@ -509,6 +542,26 @@ function formatToolValue(value) {
|
|
|
509
542
|
}
|
|
510
543
|
|
|
511
544
|
// src/ui/ink/state.ts
|
|
545
|
+
var EMPTY_INFLIGHT = { promptTokens: 0, completionTokens: 0, reasoningTokens: 0, costUsd: 0 };
|
|
546
|
+
function computeInflight(state, partial, previous) {
|
|
547
|
+
const next = {
|
|
548
|
+
promptTokens: partial.promptTokens ?? previous.promptTokens,
|
|
549
|
+
completionTokens: partial.completionTokens ?? previous.completionTokens,
|
|
550
|
+
reasoningTokens: partial.reasoningTokens ?? previous.reasoningTokens,
|
|
551
|
+
costUsd: previous.costUsd
|
|
552
|
+
};
|
|
553
|
+
if (state.provider && state.model) {
|
|
554
|
+
const cost = estimateRunCost({
|
|
555
|
+
provider: state.provider,
|
|
556
|
+
model: state.model,
|
|
557
|
+
promptTokens: next.promptTokens,
|
|
558
|
+
completionTokens: next.completionTokens,
|
|
559
|
+
reasoningTokens: next.reasoningTokens
|
|
560
|
+
});
|
|
561
|
+
next.costUsd = cost.usd;
|
|
562
|
+
}
|
|
563
|
+
return next;
|
|
564
|
+
}
|
|
512
565
|
function createInitialInkState(options = {}) {
|
|
513
566
|
const now = options.now ?? Date.now();
|
|
514
567
|
const warmupMessages = options.provider && options.model ? [{
|
|
@@ -528,6 +581,9 @@ function createInitialInkState(options = {}) {
|
|
|
528
581
|
sessionGenerateMs: options.initialGenerateMs ?? 0,
|
|
529
582
|
turnCount: options.initialTurnCount ?? 0,
|
|
530
583
|
stats: options.initialStats ?? { costUsd: 0, totalTokens: 0 },
|
|
584
|
+
inflight: { ...EMPTY_INFLIGHT },
|
|
585
|
+
provider: options.provider ?? "",
|
|
586
|
+
model: options.model ?? "",
|
|
531
587
|
pendingPermission: null
|
|
532
588
|
};
|
|
533
589
|
}
|
|
@@ -590,7 +646,9 @@ function inkReducer(state, action) {
|
|
|
590
646
|
};
|
|
591
647
|
}
|
|
592
648
|
case "turn_start":
|
|
593
|
-
return { ...state, pendingTurn: { startedAt: action.startedAt, spinnerVisible: true }, activityItems: [] };
|
|
649
|
+
return { ...state, pendingTurn: { startedAt: action.startedAt, spinnerVisible: true }, activityItems: [], inflight: { ...EMPTY_INFLIGHT } };
|
|
650
|
+
case "turn_progress":
|
|
651
|
+
return { ...state, inflight: computeInflight(state, action, state.inflight) };
|
|
594
652
|
case "turn_complete": {
|
|
595
653
|
const turnTokens = (action.promptTokens ?? 0) + (action.completionTokens ?? 0) + (action.reasoningTokens ?? 0);
|
|
596
654
|
const currentCost = state.stats.costUsd ?? 0;
|
|
@@ -605,7 +663,8 @@ function inkReducer(state, action) {
|
|
|
605
663
|
stats: {
|
|
606
664
|
costUsd: action.costUsd === null || action.costUsd === void 0 ? state.stats.costUsd : currentCost + action.costUsd,
|
|
607
665
|
totalTokens: turnTokens > 0 ? currentTokens + turnTokens : state.stats.totalTokens
|
|
608
|
-
}
|
|
666
|
+
},
|
|
667
|
+
inflight: { ...EMPTY_INFLIGHT }
|
|
609
668
|
};
|
|
610
669
|
}
|
|
611
670
|
case "turn_error":
|
|
@@ -614,6 +673,7 @@ function inkReducer(state, action) {
|
|
|
614
673
|
liveAssistantId: null,
|
|
615
674
|
pendingTurn: null,
|
|
616
675
|
activityItems: [],
|
|
676
|
+
inflight: { ...EMPTY_INFLIGHT },
|
|
617
677
|
messages: [...state.messages, {
|
|
618
678
|
id: `error-${Date.now()}-${state.messages.length}`,
|
|
619
679
|
role: "system",
|
|
@@ -650,7 +710,8 @@ function inkReducer(state, action) {
|
|
|
650
710
|
activityItems: [],
|
|
651
711
|
sessionGenerateMs: action.generateMs,
|
|
652
712
|
turnCount: action.turnCount,
|
|
653
|
-
stats: action.stats
|
|
713
|
+
stats: action.stats,
|
|
714
|
+
inflight: { ...EMPTY_INFLIGHT }
|
|
654
715
|
};
|
|
655
716
|
case "clear":
|
|
656
717
|
return { ...state, messages: [], assistantMessageIndexes: {}, liveAssistantId: null, activityItems: [] };
|
|
@@ -810,6 +871,11 @@ function App({
|
|
|
810
871
|
dispatch({ type: "user_message", content: prompt, timestampMs });
|
|
811
872
|
const startedAt = Date.now();
|
|
812
873
|
dispatch({ type: "turn_start", startedAt });
|
|
874
|
+
const estimatedPromptTokens = estimateTokens([
|
|
875
|
+
...historyRef.current,
|
|
876
|
+
{ role: "user", content: prompt }
|
|
877
|
+
]);
|
|
878
|
+
dispatch({ type: "turn_progress", promptTokens: estimatedPromptTokens });
|
|
813
879
|
const abortController = new AbortController();
|
|
814
880
|
activeAbortController.current = abortController;
|
|
815
881
|
try {
|
|
@@ -866,8 +932,9 @@ function App({
|
|
|
866
932
|
model: provider.model,
|
|
867
933
|
sessionStartMs: state.sessionStartMs,
|
|
868
934
|
stats: state.stats,
|
|
935
|
+
inflight: state.inflight,
|
|
869
936
|
now,
|
|
870
|
-
showColdStartHint: state.turnCount === 0
|
|
937
|
+
showColdStartHint: state.turnCount === 0 && state.pendingTurn === null
|
|
871
938
|
}
|
|
872
939
|
)
|
|
873
940
|
] });
|
|
@@ -947,4 +1014,4 @@ async function startInkChat(options) {
|
|
|
947
1014
|
export {
|
|
948
1015
|
startInkChat
|
|
949
1016
|
};
|
|
950
|
-
//# sourceMappingURL=runInkChat-
|
|
1017
|
+
//# sourceMappingURL=runInkChat-SVBEQCQ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/ink/runInkChat.tsx","../src/ui/ink/App.tsx","../src/agent/compression.ts","../src/ui/ink/Footer.tsx","../src/ui/ink/History.tsx","../src/ui/ink/markdown.tsx","../src/ui/ink/Input.tsx","../src/ui/ink/Spinner.tsx","../src/ui/ink/PermissionPrompt.tsx","../src/ui/ink/ActivityPanel.tsx","../src/ui/ink/sinkAdapter.ts","../src/ui/ink/state.ts","../src/ui/ink/useSessionTicker.ts"],"sourcesContent":["import React from \"react\";\nimport { render } from \"ink\";\nimport type { ChatProvider } from \"../../providers/types\";\nimport type { RunAgentOptions } from \"../../agent/runner\";\nimport { App } from \"./App\";\nimport {\n resumeBanner,\n sessionToChatHistory,\n sessionToInkMessages,\n startChatSession,\n statsToInkStats,\n} from \"../../sessions/repl\";\nimport type { InkMessage } from \"./types\";\n\nexport async function startInkChat(options: {\n provider: ChatProvider;\n cwd: string;\n routing?: RunAgentOptions[\"routing\"];\n continueSession?: boolean | undefined;\n resumeSessionId?: string | undefined;\n}): Promise<void> {\n const sessionStart = startChatSession({\n cwd: options.cwd,\n provider: options.provider.id,\n model: options.provider.model,\n continueSession: options.continueSession,\n resumeSessionId: options.resumeSessionId,\n });\n const initialMessages: InkMessage[] = [];\n if (sessionStart.notice) {\n initialMessages.push({\n id: `session-notice-${Date.now()}`,\n role: \"system\",\n content: sessionStart.notice,\n timestampMs: Date.now(),\n });\n }\n if (sessionStart.resumedSession) {\n initialMessages.push({\n id: `session-banner-${sessionStart.resumedSession.id}`,\n role: \"system\",\n content: resumeBanner(sessionStart.resumedSession),\n timestampMs: Date.now(),\n });\n initialMessages.push(...sessionToInkMessages(sessionStart.resumedSession, 10));\n }\n let summary = \"\";\n const instance = render(\n <App\n provider={options.provider}\n cwd={options.cwd}\n {...(options.routing ? { routing: options.routing } : {})}\n sessionController={sessionStart.controller}\n initialMessages={initialMessages}\n initialHistory={sessionStart.resumedSession ? sessionToChatHistory(sessionStart.resumedSession) : []}\n initialStats={statsToInkStats(sessionStart.controller.session.sessionStats)}\n initialGenerateMs={sessionStart.controller.session.sessionStats.generateMs}\n initialTurnCount={sessionStart.controller.session.sessionStats.turnCount}\n onExitSummary={(line) => {\n summary = line;\n }}\n />,\n { exitOnCtrlC: false },\n );\n await instance.waitUntilExit();\n if (summary) process.stdout.write(`${summary}\\n`);\n}\n","import React, { useEffect, useReducer, useRef } from \"react\";\nimport { Box, useApp } from \"ink\";\nimport { runAgent } from \"../../agent/runner\";\nimport { estimateTokens } from \"../../agent/compression\";\nimport type { ChatProvider } from \"../../providers/types\";\nimport type { ChatMessage } from \"../../providers/types\";\nimport type { RunAgentOptions } from \"../../agent/runner\";\nimport type { HostPermissionAnswer, PermissionRequestHandler } from \"../../safety/permissions/host\";\nimport { dispatchInteractiveCommand } from \"../../agent/chat\";\nimport { loadProjectCommands } from \"../../commands/project\";\nimport { listCommands } from \"../../commands/registry\";\nimport { formatElapsed } from \"../../utils/formatElapsed\";\nimport { Footer } from \"./Footer\";\nimport { History } from \"./History\";\nimport { Input } from \"./Input\";\nimport { PermissionPrompt } from \"./PermissionPrompt\";\nimport { ActivityPanel } from \"./ActivityPanel\";\nimport { createInkSink } from \"./sinkAdapter\";\nimport { createInitialInkState, inkReducer, type InkAction, type InkState } from \"./state\";\nimport type { InkMessage, InkSessionStats } from \"./types\";\nimport { useSessionTicker } from \"./useSessionTicker\";\nimport {\n resumeBanner,\n sessionToInkMessages,\n statsToInkStats,\n type ChatSessionController,\n} from \"../../sessions/repl\";\nimport type { ChatSession } from \"../../sessions/types\";\n\nfunction createInkCommandOutput(dispatch: React.Dispatch<InkAction>): NodeJS.WritableStream {\n return {\n write(chunk: unknown) {\n const content = String(chunk).trimEnd();\n if (content) dispatch({ type: \"system_message\", content });\n return true;\n },\n } as NodeJS.WritableStream;\n}\n\nfunction sessionSummary(state: InkState): string {\n return `Session: ${formatElapsed(Date.now() - state.sessionStartMs)} elapsed · ${formatElapsed(state.sessionGenerateMs)} generating · ${state.turnCount} turn${state.turnCount === 1 ? \"\" : \"s\"}`;\n}\n\nexport function App({\n provider,\n cwd,\n routing,\n initialMessages = [],\n initialHistory,\n initialStats,\n initialGenerateMs,\n initialTurnCount,\n sessionController,\n onSubmit,\n onExitSummary,\n}: {\n provider: ChatProvider;\n cwd: string;\n routing?: RunAgentOptions[\"routing\"];\n initialMessages?: InkMessage[] | undefined;\n initialHistory?: ChatMessage[] | undefined;\n initialStats?: InkSessionStats | undefined;\n initialGenerateMs?: number | undefined;\n initialTurnCount?: number | undefined;\n sessionController?: ChatSessionController | undefined;\n onSubmit?: (value: string) => void;\n onExitSummary?: (summary: string) => void;\n}) {\n const app = useApp();\n const [state, dispatch] = useReducer(\n inkReducer,\n {\n provider: provider.id,\n model: provider.model,\n initialMessages,\n initialStats,\n initialGenerateMs,\n initialTurnCount,\n },\n createInitialInkState,\n );\n const historyRef = useRef<ChatMessage[]>(initialHistory ?? []);\n const stateRef = useRef(state);\n const activeAbortController = useRef<AbortController | null>(null);\n const permissionResolver = useRef<((answer: HostPermissionAnswer) => void) | null>(null);\n const now = useSessionTicker(1000);\n\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n useEffect(() => {\n const handleBeforeExit = () => {\n try {\n sessionController?.materialize();\n } catch {\n // Session materialization should not mask process shutdown.\n }\n };\n process.on(\"beforeExit\", handleBeforeExit);\n return () => {\n process.off(\"beforeExit\", handleBeforeExit);\n handleBeforeExit();\n };\n }, [sessionController]);\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n await loadProjectCommands(cwd);\n if (cancelled) return;\n const projectCommandCount = listCommands().filter((command) => command.category === \"project\").length;\n dispatch({ type: \"system_message\", content: `Tanya · loaded ${projectCommandCount} project command${projectCommandCount === 1 ? \"\" : \"s\"} · ready.` });\n })();\n return () => {\n cancelled = true;\n };\n }, [cwd]);\n\n const handlePermissionRequest: PermissionRequestHandler = async (request) => {\n return new Promise((resolve) => {\n permissionResolver.current = resolve;\n dispatch({ type: \"permission_request\", request });\n });\n };\n\n const answerPermission = (answer: HostPermissionAnswer) => {\n const resolve = permissionResolver.current;\n permissionResolver.current = null;\n dispatch({ type: \"permission_clear\" });\n resolve?.(answer);\n };\n\n const handleExit = () => {\n if (stateRef.current.pendingPermission) {\n answerPermission({ decision: \"deny\" });\n dispatch({ type: \"system_message\", content: \"Denied pending permission request.\" });\n return;\n }\n if (activeAbortController.current && !activeAbortController.current.signal.aborted) {\n activeAbortController.current.abort();\n dispatch({ type: \"system_message\", content: \"Cancelled active run.\" });\n return;\n }\n try {\n sessionController?.materialize();\n } catch {\n // Session materialization should not mask UI exit.\n }\n onExitSummary?.(sessionSummary(stateRef.current));\n app.exit();\n };\n\n const handleSubmit = (value: string) => {\n if (onSubmit) {\n onSubmit(value);\n return;\n }\n void (async () => {\n const prompt = value.trim();\n if (!prompt) return;\n if (prompt.startsWith(\"/\")) {\n const output = createInkCommandOutput(dispatch);\n await dispatchInteractiveCommand(prompt, {\n provider,\n cwd,\n sink: async () => {},\n output,\n history: historyRef.current,\n ...(routing ? { routing } : {}),\n sessionController,\n clearHistory: () => {\n historyRef.current.length = 0;\n dispatch({ type: \"clear\" });\n },\n replaceHistory: (nextHistory) => {\n historyRef.current = nextHistory;\n },\n onSessionResumed: (session) => {\n replaceRenderedSession(dispatch, session);\n },\n onPermissionRequest: handlePermissionRequest,\n });\n return;\n }\n const timestampMs = Date.now();\n dispatch({ type: \"user_message\", content: prompt, timestampMs });\n const startedAt = Date.now();\n dispatch({ type: \"turn_start\", startedAt });\n const estimatedPromptTokens = estimateTokens([\n ...historyRef.current,\n { role: \"user\", content: prompt },\n ]);\n dispatch({ type: \"turn_progress\", promptTokens: estimatedPromptTokens });\n const abortController = new AbortController();\n activeAbortController.current = abortController;\n try {\n const sink = createInkSink(dispatch, {\n provider: provider.id,\n model: provider.model,\n startedAt,\n });\n const result = await runAgent({\n provider,\n prompt,\n cwd,\n sink,\n history: historyRef.current,\n signal: abortController.signal,\n onPermissionRequest: handlePermissionRequest,\n ...(routing ? { routing } : {}),\n });\n historyRef.current.push({ role: \"user\", content: prompt });\n historyRef.current.push({ role: \"assistant\", content: result.message });\n sessionController?.appendCompletedTurn(prompt, result.message, startedAt, Date.now() - startedAt, result);\n } catch (error) {\n dispatch({ type: \"turn_error\", message: error instanceof Error ? error.message : String(error) });\n } finally {\n activeAbortController.current = null;\n }\n })();\n };\n\n return (\n <Box flexDirection=\"column\" height=\"100%\" minHeight={8}>\n <History\n messages={state.messages}\n pendingTurn={state.pendingTurn}\n liveAssistantId={state.liveAssistantId}\n />\n <ActivityPanel items={state.activityItems} />\n <PermissionPrompt request={state.pendingPermission} onAnswer={answerPermission} />\n <Input\n disabled={state.pendingTurn !== null || state.pendingPermission !== null}\n {...(state.pendingTurn?.spinnerVisible ? { pendingStartedAt: state.pendingTurn.startedAt } : {})}\n now={now}\n onSubmit={handleSubmit}\n onExit={handleExit}\n />\n <Footer\n provider={provider.id}\n model={provider.model}\n sessionStartMs={state.sessionStartMs}\n stats={state.stats}\n inflight={state.inflight}\n now={now}\n showColdStartHint={state.turnCount === 0 && state.pendingTurn === null}\n />\n </Box>\n );\n}\n\nfunction replaceRenderedSession(dispatch: React.Dispatch<InkAction>, session: ChatSession): void {\n const now = Date.now();\n dispatch({\n type: \"replace_session\",\n messages: [\n {\n id: `session-banner-${session.id}-${now}`,\n role: \"system\",\n content: resumeBanner(session),\n timestampMs: now,\n },\n ...sessionToInkMessages(session, 10),\n ],\n stats: statsToInkStats(session.sessionStats),\n generateMs: session.sessionStats.generateMs,\n turnCount: session.sessionStats.turnCount,\n });\n}\n","import type { ChatMessage, ChatProvider } from \"../providers/types\";\n\nexport function estimateTokens(messages: ChatMessage[]): number {\n return messages.reduce((sum, msg) => {\n const text = typeof msg.content === \"string\" ? msg.content : JSON.stringify(msg.content ?? \"\");\n return sum + Math.ceil(text.length / 4);\n }, 0);\n}\n\nexport async function summarizeOldMessages(\n provider: ChatProvider,\n messages: ChatMessage[],\n): Promise<ChatMessage> {\n const text = messages\n .map((message) => {\n const role = message.role.toUpperCase();\n const content = typeof message.content === \"string\" ? message.content : JSON.stringify(message.content ?? \"\");\n return `[${role}]: ${content.slice(0, 800)}`;\n })\n .join(\"\\n\\n\");\n\n try {\n let summary = \"\";\n for await (const delta of provider.streamChat({\n messages: [\n {\n role: \"user\",\n content: `Summarize these agent turns into a compact factual block (max 400 words).\nInclude: what files were read, what edits were made, what commands ran and their outcomes, any blockers hit.\nDo not include reasoning or explanations — only facts.\n\n${text}`,\n },\n ],\n tools: [],\n temperature: 0,\n maxTokens: 512,\n })) {\n if (delta.content) summary += delta.content;\n }\n\n return {\n role: \"user\",\n content: `[CONTEXT SUMMARY — earlier turns compressed to save context]\\n${summary.trim()}\\n[END SUMMARY — continuing task below]`,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.warn(`[tanya] Context summarization failed; dropping ${messages.length} older turns without summarization: ${message}`);\n return {\n role: \"user\",\n content: `[CONTEXT SUMMARY — earlier turns dropped to save context]\\nDropped ${messages.length} older turns because summarization failed: ${message}\\n[END SUMMARY — continuing task below]`,\n };\n }\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { formatUsd } from \"../../memory/runLogs\";\nimport { formatElapsed } from \"../../utils/formatElapsed\";\nimport type { InflightTurn } from \"./state\";\nimport type { InkSessionStats } from \"./types\";\n\nconst divider = \"─\".repeat(80);\n\nfunction formatTokens(tokens: number | null): string {\n if (tokens === null) return \"— tokens\";\n if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M tokens`;\n if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k tokens`;\n return `${tokens} tokens`;\n}\n\nfunction formatFooterCost(costUsd: number | null): string {\n if (costUsd === null) return \"$—\";\n if (costUsd === 0) return \"$0.00\";\n return formatUsd(costUsd);\n}\n\nfunction inflightTokenTotal(inflight: InflightTurn | undefined): number {\n if (!inflight) return 0;\n return inflight.promptTokens + inflight.completionTokens + inflight.reasoningTokens;\n}\n\nexport function Footer({ provider, model, sessionStartMs, stats, inflight, now, showColdStartHint = false }: {\n provider: string;\n model: string;\n sessionStartMs: number;\n stats: InkSessionStats;\n inflight?: InflightTurn;\n now: number;\n showColdStartHint?: boolean;\n}) {\n const inflightTokens = inflightTokenTotal(inflight);\n const inflightCost = inflight?.costUsd ?? 0;\n const baseCost = stats.costUsd ?? 0;\n const liveCost = inflightTokens > 0 || inflightCost > 0 ? baseCost + inflightCost : stats.costUsd;\n const baseTokens = stats.totalTokens ?? 0;\n const liveTokens = inflightTokens > 0 ? baseTokens + inflightTokens : stats.totalTokens;\n const livePrefix = inflightTokens > 0 ? \"~\" : \"\";\n const cost = formatFooterCost(liveCost);\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{divider}</Text>\n <Text dimColor>\n {showColdStartHint\n ? \"First turn may take ~30-60s on DeepSeek V4-Pro (cold-start + skill loading).\"\n : `${provider}:${model} · session ${formatElapsed(now - sessionStartMs)} · ${livePrefix}${cost} · ${livePrefix}${formatTokens(liveTokens)} · /help`}\n </Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Static, Text } from \"ink\";\nimport { formatClock, formatElapsed } from \"../../utils/formatElapsed\";\nimport type { InkMessage } from \"./types\";\nimport type { PendingTurn } from \"./state\";\nimport { MarkdownText } from \"./markdown\";\n\nfunction messagePrefix(message: InkMessage): string {\n const clock = `[${formatClock(new Date(message.timestampMs))}]`;\n if (message.role === \"user\") return `${clock} You:`;\n if (message.role === \"assistant\") {\n return `${clock} Tanya${message.elapsedMs !== undefined ? ` · ${formatElapsed(message.elapsedMs)}` : \"\"}:`;\n }\n if (message.role === \"tool\") return `${clock} tool:`;\n return `${clock} ·`;\n}\n\nconst MessageBlock = React.memo(function MessageBlock({ message, live = false }: { message: InkMessage; live?: boolean }) {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={message.role === \"user\" ? \"green\" : message.role === \"assistant\" ? \"cyan\" : \"gray\"}>\n {messagePrefix(message)}\n </Text>\n {message.content\n ? message.role === \"assistant\"\n ? <MarkdownText source={message.content} formatPartialLine={!live} />\n : <Text wrap=\"wrap\">{message.content}</Text>\n : null}\n </Box>\n );\n}, (previous, next) => previous.live === next.live &&\n previous.message.id === next.message.id &&\n previous.message.role === next.message.role &&\n previous.message.elapsedMs === next.message.elapsedMs &&\n previous.message.content.length === next.message.content.length);\n\nexport function splitHistoryMessages(messages: InkMessage[], pendingTurn: PendingTurn | null, liveAssistantId: string | null): {\n finalized: InkMessage[];\n live: InkMessage[];\n} {\n if (!pendingTurn) return { finalized: messages, live: [] };\n\n const finalized: InkMessage[] = [];\n const live: InkMessage[] = [];\n for (const message of messages) {\n if (message.id === liveAssistantId || (message.role === \"system\" && message.timestampMs >= pendingTurn.startedAt)) {\n live.push(message);\n } else {\n finalized.push(message);\n }\n }\n return { finalized, live };\n}\n\nexport function History({ messages, pendingTurn, liveAssistantId }: {\n messages: InkMessage[];\n pendingTurn: PendingTurn | null;\n liveAssistantId: string | null;\n}) {\n const { finalized, live } = splitHistoryMessages(messages, pendingTurn, liveAssistantId);\n return (\n <Box flexDirection=\"column\" flexGrow={1} overflow=\"hidden\">\n {messages.length === 0 ? (\n <Text dimColor>Tanya chat ready.</Text>\n ) : (\n <>\n <Static<InkMessage> items={finalized}>\n {(message) => <MessageBlock key={message.id} message={message} />}\n </Static>\n {live.map((message) => (\n <MessageBlock key={message.id} message={message} live />\n ))}\n </>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\ntype InlineNode = string | React.ReactElement;\n\nfunction hasBalancedMarkers(line: string, marker: string): boolean {\n return line.split(marker).length % 2 === 1;\n}\n\nfunction renderInline(line: string): InlineNode[] {\n if (\n (line.includes(\"**\") && !hasBalancedMarkers(line, \"**\")) ||\n (line.includes(\"`\") && !hasBalancedMarkers(line, \"`\")) ||\n (line.includes(\"*\") && !line.includes(\"**\") && !hasBalancedMarkers(line, \"*\")) ||\n (line.includes(\"_\") && !hasBalancedMarkers(line, \"_\"))\n ) {\n return [line];\n }\n\n const nodes: InlineNode[] = [];\n const pattern = /(\\*\\*[^*]+\\*\\*|`[^`]+`|\\[[^\\]]+\\]\\([^)]+\\)|\\*[^*]+\\*|_[^_]+_)/g;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n let key = 0;\n while ((match = pattern.exec(line)) !== null) {\n if (match.index > lastIndex) nodes.push(line.slice(lastIndex, match.index));\n const token = match[0]!;\n if (token.startsWith(\"**\")) {\n nodes.push(<Text key={`b-${key++}`} bold>{token.slice(2, -2)}</Text>);\n } else if (token.startsWith(\"`\")) {\n nodes.push(<Text key={`c-${key++}`} inverse>{token.slice(1, -1)}</Text>);\n } else if (token.startsWith(\"[\")) {\n const linkMatch = token.match(/^\\[([^\\]]+)\\]\\(([^)]+)\\)$/);\n if (linkMatch) {\n nodes.push(\n <React.Fragment key={`l-${key++}`}>\n <Text underline>{linkMatch[1]}</Text>\n <Text dimColor> ({linkMatch[2]})</Text>\n </React.Fragment>,\n );\n }\n } else {\n nodes.push(<Text key={`i-${key++}`} italic>{token.slice(1, -1)}</Text>);\n }\n lastIndex = pattern.lastIndex;\n }\n if (lastIndex < line.length) nodes.push(line.slice(lastIndex));\n return nodes;\n}\n\nfunction renderFormattedLine(line: string, key: string): React.ReactElement {\n if (/^#{1,3}\\s/.test(line)) {\n const [, hashes = \"\", text = \"\"] = line.match(/^(#{1,3})\\s+(.*)$/) ?? [];\n return <Text key={key} bold color={hashes.length === 1 ? \"cyan\" : \"blue\"}>{renderInline(text)}</Text>;\n }\n if (/^\\s*[-*]\\s+/.test(line)) {\n return <Text key={key}>• {renderInline(line.replace(/^\\s*[-*]\\s+/, \"\"))}</Text>;\n }\n if (/^\\s*\\d+\\.\\s+/.test(line)) {\n const marker = line.match(/^\\s*(\\d+\\.)\\s+/)?.[1] ?? \"1.\";\n return <Text key={key}>{marker} {renderInline(line.replace(/^\\s*\\d+\\.\\s+/, \"\"))}</Text>;\n }\n if (/^\\s*>\\s?/.test(line)) {\n return <Text key={key} dimColor italic>│ {renderInline(line.replace(/^\\s*>\\s?/, \"\"))}</Text>;\n }\n return <Text key={key}>{renderInline(line)}</Text>;\n}\n\nexport function MarkdownText({ source, formatPartialLine = false }: { source: string; formatPartialLine?: boolean }) {\n if (!source) return null;\n\n const lines = source.split(\"\\n\");\n const hasTrailingNewline = source.endsWith(\"\\n\");\n const completeLineCount = lines.length - 1;\n const nodes: React.ReactElement[] = [];\n let index = 0;\n\n while (index < completeLineCount) {\n const line = lines[index] ?? \"\";\n if (line.startsWith(\"```\")) {\n const closingIndex = lines.findIndex((candidate, candidateIndex) => candidateIndex > index && candidate.startsWith(\"```\"));\n if (closingIndex > index && closingIndex < lines.length) {\n const code = lines.slice(index + 1, closingIndex).join(\"\\n\");\n nodes.push(\n <Box key={`code-${index}`} borderStyle=\"round\" paddingX={1} flexDirection=\"column\">\n <Text>{code}</Text>\n </Box>,\n );\n index = closingIndex + 1;\n continue;\n }\n }\n nodes.push(renderFormattedLine(line, `line-${index}`));\n index += 1;\n }\n\n if (!hasTrailingNewline) {\n const partial = lines.at(-1) ?? \"\";\n if (partial) {\n nodes.push(formatPartialLine\n ? renderFormattedLine(partial, \"partial\")\n : <Text key=\"partial\">{partial}</Text>);\n }\n }\n\n return <Box flexDirection=\"column\">{nodes}</Box>;\n}\n","import React, { useRef, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { formatClock } from \"../../utils/formatElapsed\";\nimport { Spinner } from \"./Spinner\";\n\nconst divider = \"─\".repeat(80);\n\nexport function Input({ disabled = false, pendingStartedAt, now, onSubmit, onExit }: {\n disabled?: boolean;\n pendingStartedAt?: number;\n now: number;\n onSubmit?: (value: string) => void;\n onExit?: () => void;\n}) {\n const [value, setValue] = useState(\"\");\n const valueRef = useRef(\"\");\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") {\n onExit?.();\n return;\n }\n if (key.ctrl && input === \"d\") {\n onExit?.();\n return;\n }\n if (disabled) return;\n const newlineIndex = input.search(/[\\r\\n]/);\n if (key.return || newlineIndex >= 0) {\n if (newlineIndex > 0) {\n valueRef.current += input.slice(0, newlineIndex);\n }\n const submitted = valueRef.current.trim();\n valueRef.current = \"\";\n setValue(\"\");\n if (submitted === \"/exit\" || submitted === \"/quit\") {\n onExit?.();\n return;\n }\n if (submitted) onSubmit?.(submitted);\n return;\n }\n if (key.backspace || key.delete) {\n valueRef.current = valueRef.current.slice(0, -1);\n setValue(valueRef.current);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n valueRef.current += input;\n setValue(valueRef.current);\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{divider}</Text>\n <Box>\n <Text color=\"green\">[{formatClock(new Date(now))}] > </Text>\n <Text>{disabled ? \"\" : value}</Text>\n {!disabled ? <Text inverse> </Text> : pendingStartedAt ? <Spinner startedAt={pendingStartedAt} now={now} /> : <Text dimColor>streaming…</Text>}\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Text } from \"ink\";\n\nconst frames = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\nexport function Spinner({ startedAt, now }: { startedAt: number; now: number }) {\n const elapsedMs = Math.max(0, now - startedAt);\n const frameIndex = Math.floor(elapsedMs / 120) % frames.length;\n const elapsedSec = Math.floor(elapsedMs / 1000);\n return <Text color=\"cyan\">{frames[frameIndex]} thinking… ({elapsedSec}s)</Text>;\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { HostPermissionAnswer, PermissionRequest } from \"../../safety/permissions/host\";\n\nexport function PermissionPrompt({ request, onAnswer }: {\n request: PermissionRequest | null;\n onAnswer: (answer: HostPermissionAnswer) => void;\n}) {\n useInput((input) => {\n if (!request) return;\n const normalized = input.trim().toLowerCase();\n if (normalized === \"y\") onAnswer({ decision: \"allow\" });\n if (normalized === \"n\") onAnswer({ decision: \"deny\" });\n }, { isActive: request !== null });\n\n if (!request) return null;\n const label = request.matchedRule ? `${request.tool} (${request.matchedRule})` : request.tool;\n const question = request.input && typeof request.input === \"object\" && typeof (request.input as { question?: unknown }).question === \"string\"\n ? (request.input as { question: string }).question\n : undefined;\n return (\n <Box borderStyle=\"round\" borderColor=\"yellow\" paddingX={1} marginBottom={1}>\n <Text color=\"yellow\">{question ?? `Permission required for ${label}.`} Press y to allow, n to deny.</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ActivityItem } from \"./types\";\n\nfunction activityGlyph(item: ActivityItem): string {\n if (item.kind === \"reasoning\") return \"⚙\";\n if (item.status === \"done\") return \"✓\";\n if (item.status === \"error\") return \"×\";\n return \"⚙\";\n}\n\nfunction ActivityPanelView({ items }: { items: ActivityItem[] }) {\n if (items.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n {items.map((item) => (\n <Box key={item.id} flexDirection=\"column\">\n <Text color={item.status === \"error\" ? \"red\" : item.status === \"done\" ? \"green\" : \"yellow\"}>\n {activityGlyph(item)} {item.summary}\n </Text>\n {item.kind === \"reasoning\" && item.content ? <Text dimColor italic wrap=\"wrap\">{item.content}</Text> : null}\n {item.kind === \"tool\" && item.content ? <Text dimColor wrap=\"wrap\">{item.content}</Text> : null}\n </Box>\n ))}\n </Box>\n );\n}\n\nfunction activityPanelPropsAreEqual(previous: { items: ActivityItem[] }, next: { items: ActivityItem[] }): boolean {\n const previousLast = previous.items.at(-1);\n const nextLast = next.items.at(-1);\n return previous.items.length === next.items.length &&\n previousLast?.id === nextLast?.id &&\n previousLast?.status === nextLast?.status &&\n previousLast?.summary === nextLast?.summary &&\n (previousLast?.content?.length ?? 0) === (nextLast?.content?.length ?? 0);\n}\n\nexport const ActivityPanel = React.memo(ActivityPanelView, activityPanelPropsAreEqual);\n","import type { Dispatch } from \"react\";\nimport type { EventSink, TanyaEvent } from \"../../events/types\";\nimport { estimateRunCost } from \"../../memory/runLogs\";\nimport { formatClock, formatElapsed } from \"../../utils/formatElapsed\";\nimport type { InkAction } from \"./state\";\n\nexport function createInkSink(dispatch: Dispatch<InkAction>, options: {\n provider: string;\n model: string;\n startedAt: number;\n flushIntervalMs?: number;\n}): EventSink {\n let assistantId: string | null = null;\n let streamedText = false;\n let buffer = \"\";\n let flushHandle: ReturnType<typeof setTimeout> | null = null;\n let reasoningId: string | null = null;\n let reasoningBuffer = \"\";\n let reasoningFlushHandle: ReturnType<typeof setTimeout> | null = null;\n let reasoningStartedAt: number | null = null;\n let streamedTokenChars = 0;\n let streamedReasoningChars = 0;\n let lastProgressCompletionTokens = 0;\n let lastProgressReasoningTokens = 0;\n let toolCount = 0;\n const flushIntervalMs = options.flushIntervalMs ?? 30;\n\n const dispatchProgressEstimate = () => {\n const completionTokens = Math.ceil(streamedTokenChars / 4);\n const reasoningTokens = Math.ceil(streamedReasoningChars / 4);\n if (completionTokens === lastProgressCompletionTokens && reasoningTokens === lastProgressReasoningTokens) return;\n lastProgressCompletionTokens = completionTokens;\n lastProgressReasoningTokens = reasoningTokens;\n dispatch({ type: \"turn_progress\", completionTokens, reasoningTokens });\n };\n\n const ensureAssistant = () => {\n if (assistantId) return assistantId;\n const timestampMs = Date.now();\n assistantId = `assistant-${timestampMs}`;\n dispatch({\n type: \"assistant_start\",\n id: assistantId,\n timestampMs,\n elapsedMs: timestampMs - options.startedAt,\n });\n return assistantId;\n };\n\n const flushBuffer = () => {\n if (flushHandle !== null) {\n clearTimeout(flushHandle);\n flushHandle = null;\n }\n if (!buffer) return;\n const text = buffer;\n buffer = \"\";\n dispatch({ type: \"assistant_delta\", id: ensureAssistant(), text });\n };\n\n const scheduleFlush = () => {\n if (flushHandle !== null) return;\n flushHandle = setTimeout(() => {\n flushHandle = null;\n flushBuffer();\n }, flushIntervalMs);\n };\n\n const ensureReasoning = () => {\n if (reasoningId) return reasoningId;\n const startedAt = Date.now();\n reasoningStartedAt = startedAt;\n reasoningId = `reasoning-${startedAt}`;\n dispatch({\n type: \"activity_start\",\n item: {\n id: reasoningId,\n kind: \"reasoning\",\n status: \"active\",\n summary: \"thinking…\",\n startedAt,\n },\n });\n return reasoningId;\n };\n\n const flushReasoningBuffer = () => {\n if (reasoningFlushHandle !== null) {\n clearTimeout(reasoningFlushHandle);\n reasoningFlushHandle = null;\n }\n if (!reasoningBuffer) return;\n const text = reasoningBuffer;\n reasoningBuffer = \"\";\n dispatch({ type: \"activity_progress\", id: ensureReasoning(), text });\n };\n\n const scheduleReasoningFlush = () => {\n if (reasoningFlushHandle !== null) return;\n reasoningFlushHandle = setTimeout(() => {\n reasoningFlushHandle = null;\n flushReasoningBuffer();\n }, flushIntervalMs);\n };\n\n const sink: EventSink = (event: TanyaEvent) => {\n switch (event.type) {\n case \"message_delta\": {\n streamedText = true;\n ensureAssistant();\n buffer += event.text;\n streamedTokenChars += event.text.length;\n dispatchProgressEstimate();\n scheduleFlush();\n break;\n }\n case \"message_end\":\n flushBuffer();\n break;\n case \"reasoning_chunk\":\n reasoningBuffer += event.content;\n streamedReasoningChars += event.content.length;\n dispatchProgressEstimate();\n scheduleReasoningFlush();\n break;\n case \"tool_call\": {\n flushBuffer();\n flushReasoningBuffer();\n toolCount += 1;\n dispatch({\n type: \"activity_start\",\n item: {\n id: event.id,\n kind: \"tool\",\n status: \"active\",\n summary: `running ${formatToolCallSummary(event.tool, event.input)}`,\n startedAt: Date.now(),\n },\n });\n break;\n }\n case \"tool_result\":\n flushBuffer();\n flushReasoningBuffer();\n dispatch({\n type: \"activity_end\",\n id: event.id,\n summary: `${event.tool}: ${event.summary}`,\n status: event.ok ? \"done\" : \"error\",\n endedAt: Date.now(),\n });\n break;\n case \"tool_progress\":\n flushBuffer();\n flushReasoningBuffer();\n dispatch({ type: \"activity_progress\", id: event.toolCallId, text: event.chunk.trimEnd() });\n break;\n case \"status\":\n flushBuffer();\n dispatch({ type: \"system_message\", content: event.message });\n break;\n case \"error\":\n flushBuffer();\n dispatch({ type: \"system_message\", content: `Error: ${event.message}${event.detail ? `\\n${event.detail}` : \"\"}` });\n break;\n case \"final\": {\n flushBuffer();\n flushReasoningBuffer();\n if (!streamedText && event.message.trim()) {\n buffer += event.message.trim();\n flushBuffer();\n }\n const now = Date.now();\n const streamedTokens = event.metrics?.completionTokens ?? streamedTokenChars;\n dispatch({\n type: \"system_message\",\n content: `[${formatClock(new Date(now))}] · ran ${toolCount} tool${toolCount === 1 ? \"\" : \"s\"} · thought for ${formatElapsed(\n reasoningStartedAt === null ? 0 : now - reasoningStartedAt,\n )} · streamed ${streamedTokens} token${streamedTokens === 1 ? \"\" : \"s\"}`,\n timestampMs: now,\n });\n const metrics = event.metrics;\n const cost = metrics ? estimateRunCost({\n provider: options.provider,\n model: options.model,\n promptTokens: metrics.promptTokens ?? 0,\n completionTokens: metrics.completionTokens ?? 0,\n reasoningTokens: metrics.reasoningTokens ?? 0,\n }).usd : null;\n if (event.metrics) {\n dispatch({\n type: \"turn_complete\",\n elapsedMs: Date.now() - options.startedAt,\n costUsd: cost,\n ...(metrics?.promptTokens !== undefined ? { promptTokens: metrics.promptTokens } : {}),\n ...(metrics?.completionTokens !== undefined ? { completionTokens: metrics.completionTokens } : {}),\n ...(metrics?.reasoningTokens !== undefined ? { reasoningTokens: metrics.reasoningTokens } : {}),\n });\n } else {\n dispatch({ type: \"turn_complete\", elapsedMs: Date.now() - options.startedAt, costUsd: null });\n }\n break;\n }\n default:\n break;\n }\n };\n (sink as EventSink & { tanyaSinkKind?: \"ink\" }).tanyaSinkKind = \"ink\";\n return sink;\n}\n\nfunction formatToolCallSummary(tool: string, input: unknown): string {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return `${tool}()`;\n const entries = Object.entries(input as Record<string, unknown>)\n .filter(([, value]) => value !== undefined && value !== null)\n .slice(0, 2)\n .map(([key, value]) => `${key}=${formatToolValue(value)}`);\n return `${tool}(${entries.join(\", \")})`;\n}\n\nfunction formatToolValue(value: unknown): string {\n if (typeof value === \"string\") {\n const compact = value.replace(/\\s+/g, \" \").trim();\n return `\"${compact.length > 40 ? `${compact.slice(0, 37)}...` : compact}\"`;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n if (Array.isArray(value)) return `[${value.length}]`;\n return \"{…}\";\n}\n","import type { ActivityItem, InkMessage, InkSessionStats } from \"./types\";\nimport type { PermissionRequest } from \"../../safety/permissions/host\";\nimport { estimateRunCost } from \"../../memory/runLogs\";\n\nexport interface PendingTurn {\n startedAt: number;\n spinnerVisible: boolean;\n}\n\nexport interface InflightTurn {\n promptTokens: number;\n completionTokens: number;\n reasoningTokens: number;\n costUsd: number | null;\n}\n\nexport interface InkState {\n messages: InkMessage[];\n assistantMessageIndexes: Record<string, number>;\n liveAssistantId: string | null;\n pendingTurn: PendingTurn | null;\n activityItems: ActivityItem[];\n sessionStartMs: number;\n sessionGenerateMs: number;\n turnCount: number;\n stats: InkSessionStats;\n inflight: InflightTurn;\n provider: string;\n model: string;\n pendingPermission: PermissionRequest | null;\n}\n\nconst EMPTY_INFLIGHT: InflightTurn = { promptTokens: 0, completionTokens: 0, reasoningTokens: 0, costUsd: 0 };\n\nfunction computeInflight(state: { provider: string; model: string }, partial: { promptTokens?: number; completionTokens?: number; reasoningTokens?: number }, previous: InflightTurn): InflightTurn {\n const next: InflightTurn = {\n promptTokens: partial.promptTokens ?? previous.promptTokens,\n completionTokens: partial.completionTokens ?? previous.completionTokens,\n reasoningTokens: partial.reasoningTokens ?? previous.reasoningTokens,\n costUsd: previous.costUsd,\n };\n if (state.provider && state.model) {\n const cost = estimateRunCost({\n provider: state.provider,\n model: state.model,\n promptTokens: next.promptTokens,\n completionTokens: next.completionTokens,\n reasoningTokens: next.reasoningTokens,\n });\n next.costUsd = cost.usd;\n }\n return next;\n}\n\nexport interface InitialInkStateOptions {\n provider?: string | undefined;\n model?: string | undefined;\n now?: number | undefined;\n initialMessages?: InkMessage[] | undefined;\n initialStats?: InkSessionStats | undefined;\n initialGenerateMs?: number | undefined;\n initialTurnCount?: number | undefined;\n}\n\nexport type InkAction =\n | { type: \"user_message\"; content: string; timestampMs: number }\n | { type: \"system_message\"; content: string; timestampMs?: number }\n | { type: \"assistant_start\"; id: string; timestampMs: number; elapsedMs: number }\n | { type: \"assistant_delta\"; id: string; text: string }\n | { type: \"turn_start\"; startedAt: number }\n | { type: \"turn_progress\"; promptTokens?: number; completionTokens?: number; reasoningTokens?: number }\n | { type: \"turn_complete\"; elapsedMs: number; promptTokens?: number; completionTokens?: number; reasoningTokens?: number; costUsd?: number | null }\n | { type: \"turn_error\"; message: string }\n | { type: \"activity_start\"; item: ActivityItem }\n | { type: \"activity_progress\"; id: string; text: string }\n | { type: \"activity_end\"; id: string; summary: string; status: \"done\" | \"error\"; endedAt: number }\n | { type: \"permission_request\"; request: PermissionRequest }\n | { type: \"permission_clear\" }\n | { type: \"replace_session\"; messages: InkMessage[]; stats: InkSessionStats; generateMs: number; turnCount: number }\n | { type: \"clear\" };\n\nexport function createInitialInkState(options: InitialInkStateOptions = {}): InkState {\n const now = options.now ?? Date.now();\n const warmupMessages: InkMessage[] = options.provider && options.model\n ? [{\n id: `system-connect-${now}`,\n role: \"system\",\n content: `Tanya · connecting to ${options.provider}:${options.model}…`,\n timestampMs: now,\n }]\n : [];\n const messages = [...warmupMessages, ...(options.initialMessages ?? [])];\n return {\n messages,\n assistantMessageIndexes: {},\n liveAssistantId: null,\n pendingTurn: null,\n activityItems: [],\n sessionStartMs: now,\n sessionGenerateMs: options.initialGenerateMs ?? 0,\n turnCount: options.initialTurnCount ?? 0,\n stats: options.initialStats ?? { costUsd: 0, totalTokens: 0 },\n inflight: { ...EMPTY_INFLIGHT },\n provider: options.provider ?? \"\",\n model: options.model ?? \"\",\n pendingPermission: null,\n };\n}\n\nexport function inkReducer(state: InkState, action: InkAction): InkState {\n switch (action.type) {\n case \"user_message\":\n return {\n ...state,\n messages: [...state.messages, {\n id: `user-${action.timestampMs}-${state.messages.length}`,\n role: \"user\",\n content: action.content,\n timestampMs: action.timestampMs,\n }],\n };\n case \"system_message\":\n return {\n ...state,\n messages: [...state.messages, {\n id: `system-${action.timestampMs ?? Date.now()}-${state.messages.length}`,\n role: \"system\",\n content: action.content,\n timestampMs: action.timestampMs ?? Date.now(),\n }],\n };\n case \"assistant_start\":\n if (state.messages.some((message) => message.id === action.id)) return state;\n return {\n ...state,\n pendingTurn: state.pendingTurn ? { ...state.pendingTurn, spinnerVisible: false } : state.pendingTurn,\n messages: [...state.messages, {\n id: action.id,\n role: \"assistant\",\n content: \"\",\n timestampMs: action.timestampMs,\n elapsedMs: action.elapsedMs,\n }],\n assistantMessageIndexes: {\n ...state.assistantMessageIndexes,\n [action.id]: state.messages.length,\n },\n liveAssistantId: action.id,\n };\n case \"assistant_delta\": {\n const cachedIndex = state.assistantMessageIndexes[action.id];\n const index = cachedIndex !== undefined && state.messages[cachedIndex]?.id === action.id\n ? cachedIndex\n : state.messages.findIndex((message) => message.id === action.id);\n if (index < 0) return state;\n const messages = state.messages.slice();\n const message = messages[index]!;\n messages[index] = { ...message, content: `${message.content}${action.text}` };\n return {\n ...state,\n messages,\n ...(cachedIndex === index ? {} : {\n assistantMessageIndexes: {\n ...state.assistantMessageIndexes,\n [action.id]: index,\n },\n }),\n };\n }\n case \"turn_start\":\n return { ...state, pendingTurn: { startedAt: action.startedAt, spinnerVisible: true }, activityItems: [], inflight: { ...EMPTY_INFLIGHT } };\n case \"turn_progress\":\n return { ...state, inflight: computeInflight(state, action, state.inflight) };\n case \"turn_complete\": {\n const turnTokens = (action.promptTokens ?? 0) + (action.completionTokens ?? 0) + (action.reasoningTokens ?? 0);\n const currentCost = state.stats.costUsd ?? 0;\n const currentTokens = state.stats.totalTokens ?? 0;\n return {\n ...state,\n liveAssistantId: null,\n pendingTurn: null,\n activityItems: [],\n sessionGenerateMs: state.sessionGenerateMs + action.elapsedMs,\n turnCount: state.turnCount + 1,\n stats: {\n costUsd: action.costUsd === null || action.costUsd === undefined ? state.stats.costUsd : currentCost + action.costUsd,\n totalTokens: turnTokens > 0 ? currentTokens + turnTokens : state.stats.totalTokens,\n },\n inflight: { ...EMPTY_INFLIGHT },\n };\n }\n case \"turn_error\":\n return {\n ...state,\n liveAssistantId: null,\n pendingTurn: null,\n activityItems: [],\n inflight: { ...EMPTY_INFLIGHT },\n messages: [...state.messages, {\n id: `error-${Date.now()}-${state.messages.length}`,\n role: \"system\",\n content: `Error: ${action.message}`,\n timestampMs: Date.now(),\n }],\n };\n case \"activity_start\":\n return {\n ...state,\n activityItems: [...state.activityItems, action.item],\n };\n case \"activity_progress\":\n return {\n ...state,\n activityItems: state.activityItems.map((item) => item.id === action.id\n ? { ...item, content: `${item.content ?? \"\"}${action.text}` }\n : item),\n };\n case \"activity_end\":\n return {\n ...state,\n activityItems: state.activityItems.map((item) => item.id === action.id\n ? { ...item, status: action.status, summary: action.summary, endedAt: action.endedAt }\n : item),\n };\n case \"permission_request\":\n return { ...state, pendingPermission: action.request };\n case \"permission_clear\":\n return { ...state, pendingPermission: null };\n case \"replace_session\":\n return {\n ...state,\n messages: action.messages,\n assistantMessageIndexes: {},\n liveAssistantId: null,\n pendingTurn: null,\n activityItems: [],\n sessionGenerateMs: action.generateMs,\n turnCount: action.turnCount,\n stats: action.stats,\n inflight: { ...EMPTY_INFLIGHT },\n };\n case \"clear\":\n return { ...state, messages: [], assistantMessageIndexes: {}, liveAssistantId: null, activityItems: [] };\n default:\n return state;\n }\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useSessionTicker(intervalMs = 1000): number {\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(timer);\n }, [intervalMs]);\n\n return now;\n}\n"],"mappings":"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","names":["useEffect","useRef","Box","React","Box","Text","Box","Text","jsx","jsxs","jsx","jsxs","React","MessageBlock","Box","Text","Box","Text","Text","jsxs","jsx","jsxs","divider","Box","Text","Box","Text","useInput","jsx","jsxs","React","Box","Text","jsx","jsxs","message","useState","jsx","jsxs","useRef","useEffect","Box","jsx"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matheuskrumenauer/tanya",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.6",
|
|
4
4
|
"description": "A live, tool-using AI CLI for DeepSeek and OpenAI-compatible providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"smoke:examples": "node scripts/smoke-examples.mjs",
|
|
31
31
|
"test": "vitest run",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
|
+
"publish:npm": "node scripts/npm-publish.mjs",
|
|
33
34
|
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|