@saadnvd1/agent-os 0.3.470 → 0.3.472
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 +139 -36
- package/app/api/fresh-start/route.ts +9 -5
- package/app/api/models/route.ts +34 -0
- package/app/api/models/test/route.ts +17 -0
- package/app/api/sessions/[id]/summarize/route.ts +4 -1
- package/app/api/tasks/[id]/model/route.ts +23 -0
- package/app/api/tasks/route.ts +5 -1
- package/app/api/usage/compare/route.ts +21 -0
- package/app/api/usage/route.ts +8 -3
- package/app/api/workspaces/[id]/models/route.ts +27 -0
- package/components/Chat/ChatPanel.tsx +5 -5
- package/components/Chat/StaleChip.tsx +7 -6
- package/components/CommandPalette/useAppCommands.ts +19 -1
- package/components/Draft/DraftChips.tsx +28 -0
- package/components/Draft/DraftPanel.tsx +1 -1
- package/components/Models/ModelSelect.tsx +67 -0
- package/components/Models/ModelsSection.tsx +199 -0
- package/components/Models/ProviderCard.tsx +271 -0
- package/components/SessionList/SidebarHeader.tsx +5 -1
- package/components/Settings/SettingsDialog.test.ts +3 -0
- package/components/Settings/SettingsDialog.tsx +9 -0
- package/components/Settings/commands.ts +19 -0
- package/components/Settings/entry-points.test.ts +1 -0
- package/components/Tasks/ResumeOnModel.tsx +72 -0
- package/components/Tasks/TaskRow.tsx +4 -0
- package/components/Usage/CompareView.tsx +211 -0
- package/components/Usage/ModelSpend.tsx +133 -0
- package/components/Usage/UsageDialog.tsx +69 -5
- package/components/Usage/format.ts +9 -0
- package/components/Workspaces/FreshStartForm.tsx +13 -13
- package/components/Workspaces/WorkspaceModelsForm.tsx +71 -0
- package/components/Workspaces/WorkspaceSettings.tsx +2 -0
- package/data/models/index.ts +125 -0
- package/data/usage/index.ts +5 -0
- package/lib/agents/launch.ts +13 -2
- package/lib/chat/context.ts +1 -1
- package/lib/chat/refresh.ts +31 -13
- package/lib/chat/runner.ts +5 -0
- package/lib/chat/stale.ts +25 -16
- package/lib/chat/worker/extras.ts +12 -0
- package/lib/chat/worker/host.ts +70 -24
- package/lib/chat/worker/main.ts +5 -2
- package/lib/db/migrations.ts +70 -0
- package/lib/db/types.ts +6 -0
- package/lib/drafts.ts +3 -0
- package/lib/models/config.ts +218 -0
- package/lib/models/launch.ts +93 -0
- package/lib/models/plan-step.ts +94 -0
- package/lib/models/providers.ts +163 -0
- package/lib/models/resolve.ts +246 -0
- package/lib/models/resume.ts +99 -0
- package/lib/models/roles.ts +98 -0
- package/lib/models/secrets.ts +86 -0
- package/lib/models/session-model.ts +40 -0
- package/lib/models/test-provider.ts +116 -0
- package/lib/orchestrator/act.ts +13 -1
- package/lib/orchestrator/armed.ts +1 -2
- package/lib/orchestrator/brief.ts +5 -4
- package/lib/orchestrator/claude-cli.ts +48 -14
- package/lib/orchestrator/diff.ts +1 -1
- package/lib/orchestrator/external-gates.ts +8 -43
- package/lib/orchestrator/gates.ts +10 -10
- package/lib/orchestrator/home.ts +2 -2
- package/lib/orchestrator/pr-wake.ts +2 -2
- package/lib/orchestrator/rebase.ts +6 -45
- package/lib/orchestrator/review.ts +20 -5
- package/lib/orchestrator/scope.ts +11 -0
- package/lib/orchestrator/serve.ts +13 -0
- package/lib/orchestrator/signoff.ts +13 -8
- package/lib/orchestrator/tool-names.ts +1 -0
- package/lib/orchestrator/tool-schemas.ts +38 -0
- package/lib/orchestrator/tools.ts +3 -1
- package/lib/pr-generation.ts +5 -2
- package/lib/providers/registry.ts +1 -1
- package/lib/session-audit/render.ts +1 -1
- package/lib/session-titles.ts +1 -1
- package/lib/sessions/launch.ts +19 -4
- package/lib/settings-url.ts +1 -0
- package/lib/stacks/land.ts +23 -16
- package/lib/tasks/brief.ts +3 -14
- package/lib/tasks/code-review.ts +69 -107
- package/lib/tasks/gh.ts +3 -2
- package/lib/tasks/index.ts +60 -9
- package/lib/tasks/queue.ts +14 -5
- package/lib/tasks/start.ts +7 -2
- package/lib/tasks/state.ts +4 -4
- package/lib/usage/by-model.ts +105 -0
- package/lib/usage/check-runs.ts +170 -0
- package/lib/usage/compare.ts +280 -0
- package/lib/usage/cost.ts +71 -0
- package/lib/usage/report.ts +51 -0
- package/lib/usage/turns.ts +107 -18
- package/package.json +1 -1
- package/stores/usageUi.ts +11 -2
- package/scripts/check-code-review.ts +0 -21
package/lib/usage/turns.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import { db, type Session } from "../db";
|
|
8
8
|
import type { UsageTotals } from "../chat/events";
|
|
9
9
|
import { totalTokens, turnDelta } from "../chat/context";
|
|
10
|
+
import { readUsage } from "../orchestrator/usage";
|
|
11
|
+
import { ANTHROPIC, sessionRole } from "../models/roles";
|
|
10
12
|
|
|
11
13
|
// Where a worker's totals start: a resumed conversation continues from the
|
|
12
14
|
// totals its transcript saved, which the last worker stored; a new one
|
|
@@ -30,12 +32,22 @@ function savedTotals(sessionId: string): UsageTotals | null {
|
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
//
|
|
35
|
+
// The plan's 5-hour window when a turn on it ended, for its share of the
|
|
36
|
+
// plan (lib/usage/compare): unknown when the statusline isn't sampling.
|
|
37
|
+
export function planWindowPct(): number | null {
|
|
38
|
+
const u = readUsage();
|
|
39
|
+
return "window" in u && u.window ? u.window.pct : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Records the turn, with the model, provider and role it ran as, and
|
|
43
|
+
// returns the totals to measure the next one from.
|
|
34
44
|
export function recordTurn(
|
|
35
45
|
session: Pick<Session, "id" | "name" | "workspace_id">,
|
|
36
46
|
prev: UsageTotals | null,
|
|
37
47
|
totals: UsageTotals,
|
|
38
|
-
at = Date.now()
|
|
48
|
+
at = Date.now(),
|
|
49
|
+
durationMs: number | null = null,
|
|
50
|
+
windowPct: () => number | null = planWindowPct
|
|
39
51
|
): UsageTotals {
|
|
40
52
|
const turn = turnDelta(prev, totals);
|
|
41
53
|
db.transaction(() => {
|
|
@@ -46,25 +58,102 @@ export function recordTurn(
|
|
|
46
58
|
// A local command (/context, /mcp) spends nothing.
|
|
47
59
|
if (turn.costUsd <= 0 && totalTokens(turn) <= 0) return;
|
|
48
60
|
const current = db
|
|
49
|
-
.prepare(
|
|
61
|
+
.prepare(
|
|
62
|
+
`SELECT name, workspace_id, model, model_provider, role, task_status,
|
|
63
|
+
plan_phase FROM sessions WHERE id = ?`
|
|
64
|
+
)
|
|
50
65
|
.get(session.id) as
|
|
51
|
-
|
|
|
66
|
+
| Pick<
|
|
67
|
+
Session,
|
|
68
|
+
| "name"
|
|
69
|
+
| "workspace_id"
|
|
70
|
+
| "model"
|
|
71
|
+
| "model_provider"
|
|
72
|
+
| "role"
|
|
73
|
+
| "task_status"
|
|
74
|
+
| "plan_phase"
|
|
75
|
+
>
|
|
52
76
|
| undefined;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
session.id,
|
|
59
|
-
current?.name ?? session.name,
|
|
60
|
-
current?.workspace_id ?? session.workspace_id,
|
|
77
|
+
const provider = current?.model_provider ?? ANTHROPIC;
|
|
78
|
+
insertTurn({
|
|
79
|
+
sessionId: session.id,
|
|
80
|
+
sessionName: current?.name ?? session.name,
|
|
81
|
+
workspaceId: current?.workspace_id ?? session.workspace_id,
|
|
61
82
|
at,
|
|
62
|
-
turn
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
turn,
|
|
84
|
+
model: current?.model ?? null,
|
|
85
|
+
provider,
|
|
86
|
+
role: current ? sessionRole(current) : null,
|
|
87
|
+
durationMs,
|
|
88
|
+
windowPct: provider === ANTHROPIC ? windowPct() : null,
|
|
89
|
+
});
|
|
68
90
|
})();
|
|
69
91
|
return totals;
|
|
70
92
|
}
|
|
93
|
+
|
|
94
|
+
// Records one compaction: who ran it ("auto" is the agent's own, at its
|
|
95
|
+
// auto-compact window; "threshold" and "stale" are AgentOS's before a
|
|
96
|
+
// message; "manual" is a /compact someone typed), and the context before
|
|
97
|
+
// and after when the agent said.
|
|
98
|
+
export function recordCompaction(
|
|
99
|
+
session: Pick<Session, "id" | "name" | "workspace_id">,
|
|
100
|
+
c: { trigger: string; before?: number; after?: number },
|
|
101
|
+
at = Date.now()
|
|
102
|
+
): void {
|
|
103
|
+
const current = db
|
|
104
|
+
.prepare(`SELECT name, workspace_id FROM sessions WHERE id = ?`)
|
|
105
|
+
.get(session.id) as
|
|
106
|
+
| { name: string; workspace_id: string | null }
|
|
107
|
+
| undefined;
|
|
108
|
+
db.prepare(
|
|
109
|
+
`INSERT INTO chat_compactions (session_id, session_name, workspace_id, at, trigger, before_tokens, after_tokens)
|
|
110
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
111
|
+
).run(
|
|
112
|
+
session.id,
|
|
113
|
+
current?.name ?? session.name,
|
|
114
|
+
current?.workspace_id ?? session.workspace_id,
|
|
115
|
+
at,
|
|
116
|
+
c.trigger,
|
|
117
|
+
c.before ?? null,
|
|
118
|
+
c.after ?? null
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface TurnRecord {
|
|
123
|
+
sessionId: string;
|
|
124
|
+
sessionName: string;
|
|
125
|
+
workspaceId: string | null;
|
|
126
|
+
at: number;
|
|
127
|
+
turn: UsageTotals;
|
|
128
|
+
model: string | null;
|
|
129
|
+
provider: string;
|
|
130
|
+
role: string | null;
|
|
131
|
+
durationMs: number | null;
|
|
132
|
+
windowPct: number | null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// One row of the usage ledger: a chat turn, or a one-shot check's run.
|
|
136
|
+
export function insertTurn(r: TurnRecord): void {
|
|
137
|
+
const { turn } = r;
|
|
138
|
+
db.prepare(
|
|
139
|
+
`INSERT INTO chat_turns (session_id, session_name, workspace_id, at, cost_usd,
|
|
140
|
+
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
141
|
+
model, provider, role, duration_ms, window_pct)
|
|
142
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
143
|
+
).run(
|
|
144
|
+
r.sessionId,
|
|
145
|
+
r.sessionName,
|
|
146
|
+
r.workspaceId,
|
|
147
|
+
r.at,
|
|
148
|
+
turn.costUsd,
|
|
149
|
+
turn.inputTokens,
|
|
150
|
+
turn.outputTokens,
|
|
151
|
+
turn.cacheReadTokens,
|
|
152
|
+
turn.cacheWriteTokens,
|
|
153
|
+
r.model,
|
|
154
|
+
r.provider,
|
|
155
|
+
r.role,
|
|
156
|
+
r.durationMs,
|
|
157
|
+
r.windowPct
|
|
158
|
+
);
|
|
159
|
+
}
|
package/package.json
CHANGED
package/stores/usageUi.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { proxy } from "valtio";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export type UsageTab = "spend" | "models" | "compare";
|
|
4
|
+
|
|
5
|
+
export const usageUi = proxy<{ open: boolean; tab: UsageTab }>({
|
|
6
|
+
open: false,
|
|
7
|
+
tab: "spend",
|
|
8
|
+
});
|
|
4
9
|
|
|
5
10
|
export const usageUiActions = {
|
|
6
|
-
open: () => {
|
|
11
|
+
open: (tab: UsageTab = "spend") => {
|
|
12
|
+
usageUi.tab = tab;
|
|
7
13
|
usageUi.open = true;
|
|
8
14
|
},
|
|
9
15
|
setOpen: (open: boolean) => {
|
|
10
16
|
usageUi.open = open;
|
|
11
17
|
},
|
|
18
|
+
setTab: (tab: UsageTab) => {
|
|
19
|
+
usageUi.tab = tab;
|
|
20
|
+
},
|
|
12
21
|
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// CI: fail a pull request whose body has no Code review section for its
|
|
2
|
-
// head commit (the same rule the orchestrator's sign_off and stacks' land
|
|
3
|
-
// apply). Reads PR_BODY and HEAD_SHA from the environment.
|
|
4
|
-
import { codeReviewRefusal, parseCodeReview } from "../lib/tasks/code-review";
|
|
5
|
-
|
|
6
|
-
// A head AgentOS rebased itself is covered by the review of the head it
|
|
7
|
-
// rebased, as its gates allow.
|
|
8
|
-
const section = parseCodeReview(process.env.PR_BODY ?? "");
|
|
9
|
-
const refusal = codeReviewRefusal(
|
|
10
|
-
section,
|
|
11
|
-
process.env.HEAD_SHA || undefined,
|
|
12
|
-
section?.restacked
|
|
13
|
-
);
|
|
14
|
-
if (refusal) {
|
|
15
|
-
console.error(`✗ ${refusal}.`);
|
|
16
|
-
console.error(
|
|
17
|
-
"Run /do-code-review on the branch, then put its section in the PR body:\n\n## Code review\nReviewed: <head sha>\nAgents: ...\nFixed: ...\nDeferred: ..."
|
|
18
|
-
);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
console.log(`✓ the Code review section covers ${process.env.HEAD_SHA}`);
|