Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ paseo agent archive <id> # 测完归档,别

- **发布代码禁止 import `@getpaseo/client` / `@getpaseo/protocol`**(含 type-only)。宿主编译插件时会解析 type-only import,但只提供 SDK specifier、zod、react、react-native、@tanstack/react-query、@types/node。git 安装不跑 `npm install`(只跑 manifest `build`),npm 安装不装 devDependencies,所以其他类型依赖会让安装失败(0.11.1 实测 `Could not resolve type dependency`)。客户端类型从 `client/paseo-types.ts` 取,服务端从 `server/paseo-types.ts` 取(都由宿主 `PaseoApi` 推导)。`shared/` 不能 import `/client` 或 `/server` SDK,用结构类型和泛型。测试文件不进 bundle,可以继续用 devDependencies。
- 改动依赖或 import 后,用无 `node_modules` 的副本验证:复制源码到临时目录、改 manifest id、让 contribute 提前返回,`paseo plugin add <目录>`,看到 "Plugin ready" 后 `paseo plugin remove` 并删除目录。
- 总览是 `addScreen`(id `ledger-overview` 不变),`range` 放在 screen params 里(`today`/`7d`/`30d`/`all`,缺省 all)。screen props 没有 setParams;切换范围用 `client.openScreen`(宿主 router.push,会产生历史记录),标题函数随 params 变化。
- 总览是 `addScreen`(id `ledger-overview` 不变),`range` 放在 screen params 里(`today`/`7d`/`30d`/`all`,缺省 all)作为**初始**范围;屏内切换是组件 state。screen props 没有 setParams,`client.openScreen` 是宿主 router.push——每调一次叠一条历史,所以屏内切换不能走导航(曾导致点 range 按钮刷屏历史记录);标题用静态字符串,params 派生标题在本地切换后会过期。
- 侧边栏是 `addSidebarFooterItem` + `SidebarRow`,trailing 显示今日费用。"今天"按客户端本地午夜计算,以 ISO `since` 传给 `ledger.overview`;服务端按 `Date.parse(endedAt)` 过滤 read-model 行,不在服务端猜时区。
- `addSurface` / `addSidebarItem` / `openSurface` 已弃用,不要再用。不接 `registerUsageSource`(那是订阅额度窗口,不是逐轮 usage;用户已决定不放进 Usage 面板)。
- 0.11.1 仍未公开 cache-write 和 provider 内部子代理 usage。
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Per-turn LLM token usage and cost for [Paseo](https://paseo.sh) agents — an ag

**Sidebar** — a **TokenLedger** row in the sidebar footer shows today's cost (or tokens when no price is known), with an activity icon while a turn is running. "Today" starts at local midnight on the device that shows it.

**Overview** (sidebar footer → TokenLedger, or the command center) — all sessions in one place: grand totals, then per-agent rows grouped by workspace with live-turn indicator, last activity, cost/tokens, and turn count. Pick **Today**, **Last 7 days**, **Last 30 days**, or **All time**; the range is part of the screen link and its title. A range lists agents with turns that ended in it, plus agents with a turn in flight. Tapping a row jumps to that agent.
**Overview** (sidebar footer → TokenLedger, or the command center) — all sessions in one place: grand totals, then per-agent rows grouped by workspace with live-turn indicator, last activity, cost/tokens, and turn count. Pick **Today**, **Last 7 days**, **Last 30 days**, or **All time**. The sidebar row opens it on Today; the command center opens All time. A range lists agents with turns that ended in it, plus agents with a turn in flight. Tapping a row jumps to that agent.

<p align="center">
<img src="images/screenshot-overview.png" alt="TokenLedger overview on Last 7 days with demo data: range buttons, totals for all sessions, and agent rows grouped by workspace; the TokenLedger row in the sidebar footer shows today's cost" width="720">
Expand Down
13 changes: 7 additions & 6 deletions client/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useDenseLayout } from "./layout.ts";
import type { PluginTheme } from "@getpaseo/plugin";
import { type PluginScreenProps } from "@getpaseo/plugin/client";
import { ScrollView } from "@getpaseo/plugin/client/react-native";
import { useMemo } from "react";
import { useEffect, useMemo, useState } from "react";
import { useOverview } from "./data.ts";
import { Pressable, Text, View } from "react-native";
import type { AgentUsageRow } from "../shared/ledger.ts";
Expand Down Expand Up @@ -99,15 +99,16 @@ function RangePicker({ range, theme, onRange }: { range: Range; theme: PluginThe
);
}

/** The range lives in the screen params, so the header title and deep links follow it. */
/** Params seed the initial range; switching is local — openScreen is router.push and stacks history. */
export function TokenLedgerOverview({
theme,
layout,
navigation,
params,
onRange,
}: PluginScreenProps & { onRange: (range: Range) => void }) {
const range = parseRange(params.range);
}: PluginScreenProps) {
const paramRange = parseRange(params.range);
const [range, setRange] = useState(paramRange);
useEffect(() => setRange(paramRange), [paramRange]);
const { data, error } = useOverview(useRangeStart(range));
const { dense, setWidth } = useDenseLayout(layout.compact);

Expand All @@ -129,7 +130,7 @@ export function TokenLedgerOverview({

return (
<ScrollView style={styles.screen} contentContainerStyle={styles.content} onLayout={(event) => setWidth(event.nativeEvent.layout.width)}>
<RangePicker range={range} theme={theme} onRange={onRange} />
<RangePicker range={range} theme={theme} onRange={setRange} />
{error ? <Text style={{ color: theme.colors.statusDanger, fontSize: 13 }}>{String(error)}</Text> : null}
{data ? (
<>
Expand Down
11 changes: 4 additions & 7 deletions index.client.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { PluginClientContext, PluginScreenProps } from "@getpaseo/plugin/client";
import type { PluginClientContext } from "@getpaseo/plugin/client";
import { TokenLedgerOverview } from "./client/overview.tsx";
import { TokenLedgerPanel } from "./client/panel.tsx";
import { contributePills } from "./client/pill.tsx";
import { OVERVIEW_SCREEN, parseRange, RANGE_LABELS } from "./client/range.ts";
import { OVERVIEW_SCREEN } from "./client/range.ts";
import { LedgerSidebarItem } from "./client/sidebar.tsx";

import { createPanelPlacement } from "./client/layout.ts";
Expand All @@ -22,13 +22,10 @@ export default function contribute(client: PluginClientContext) {
locations: ["workspace", "explorer"],
Component: TokenLedgerPanel,
});
function OverviewScreen(props: PluginScreenProps) {
return <TokenLedgerOverview {...props} onRange={(range) => client.openScreen({ screenId: OVERVIEW_SCREEN, params: { range } })} />;
}
client.addScreen({
id: OVERVIEW_SCREEN,
title: (params) => `TokenLedger · ${RANGE_LABELS[parseRange(params.range)]}`,
Component: OverviewScreen,
title: "TokenLedger",
Component: TokenLedgerOverview,
});
client.addSidebarFooterItem({ id: "ledger-today", title: "TokenLedger", Component: LedgerSidebarItem });
client.addCommandCenterItem({
Expand Down
Loading