stagent 0.1.11 → 0.1.13
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 +74 -49
- package/package.json +3 -2
- package/public/readme/cost-usage-list.png +0 -0
- package/public/readme/dashboard-bulk-select.png +0 -0
- package/public/readme/dashboard-card-edit.png +0 -0
- package/public/readme/dashboard-create-form-ai-applied.png +0 -0
- package/public/readme/dashboard-create-form-ai-assist.png +0 -0
- package/public/readme/dashboard-create-form-empty.png +0 -0
- package/public/readme/dashboard-create-form-filled.png +0 -0
- package/public/readme/dashboard-filtered.png +0 -0
- package/public/readme/dashboard-list.png +0 -0
- package/public/readme/dashboard-workflow-confirm.png +0 -0
- package/public/readme/home-below-fold.png +0 -0
- package/public/readme/home-list.png +0 -0
- package/public/readme/inbox-list.png +0 -0
- package/public/readme/playbook-list.png +0 -0
- package/public/readme/profiles-list.png +0 -0
- package/public/readme/settings-list.png +0 -0
- package/public/readme/workflows-list.png +0 -0
- package/src/__tests__/e2e/blueprint.test.ts +63 -0
- package/src/__tests__/e2e/cross-runtime.test.ts +77 -0
- package/src/__tests__/e2e/helpers.ts +286 -0
- package/src/__tests__/e2e/parallel-workflow.test.ts +120 -0
- package/src/__tests__/e2e/sequence-workflow.test.ts +109 -0
- package/src/__tests__/e2e/setup.ts +156 -0
- package/src/__tests__/e2e/single-task.test.ts +170 -0
- package/src/app/api/command-palette/recent/route.ts +41 -18
- package/src/app/api/context/batch/route.ts +44 -0
- package/src/app/api/permissions/presets/route.ts +80 -0
- package/src/app/api/playbook/status/route.ts +15 -0
- package/src/app/api/profiles/route.ts +23 -20
- package/src/app/api/settings/pricing/route.ts +15 -0
- package/src/app/api/tasks/[id]/route.ts +54 -3
- package/src/app/api/workflows/[id]/route.ts +43 -4
- package/src/app/api/workflows/[id]/status/route.ts +70 -2
- package/src/app/api/workflows/from-assist/route.ts +6 -32
- package/src/app/costs/page.tsx +53 -43
- package/src/app/dashboard/page.tsx +59 -21
- package/src/app/documents/[id]/page.tsx +10 -8
- package/src/app/globals.css +11 -0
- package/src/app/page.tsx +60 -3
- package/src/app/playbook/[slug]/page.tsx +76 -0
- package/src/app/playbook/page.tsx +54 -0
- package/src/app/profiles/page.tsx +7 -4
- package/src/app/settings/page.tsx +2 -2
- package/src/app/tasks/[id]/page.tsx +22 -2
- package/src/components/costs/cost-dashboard.tsx +226 -320
- package/src/components/dashboard/activity-feed.tsx +6 -2
- package/src/components/dashboard/greeting.tsx +3 -1
- package/src/components/dashboard/priority-queue.tsx +58 -9
- package/src/components/dashboard/stats-cards.tsx +16 -2
- package/src/components/documents/document-chip-bar.tsx +183 -0
- package/src/components/documents/document-content-renderer.tsx +146 -0
- package/src/components/documents/document-detail-view.tsx +16 -239
- package/src/components/documents/image-zoom-view.tsx +60 -0
- package/src/components/documents/smart-extracted-text.tsx +47 -0
- package/src/components/documents/utils.ts +70 -0
- package/src/components/notifications/batch-proposal-review.tsx +150 -0
- package/src/components/notifications/inbox-list.tsx +4 -5
- package/src/components/notifications/notification-item.tsx +73 -6
- package/src/components/notifications/pending-approval-host.tsx +63 -14
- package/src/components/playbook/adoption-heatmap.tsx +69 -0
- package/src/components/playbook/journey-card.tsx +110 -0
- package/src/components/playbook/playbook-action-button.tsx +22 -0
- package/src/components/playbook/playbook-browser.tsx +143 -0
- package/src/components/playbook/playbook-card.tsx +102 -0
- package/src/components/playbook/playbook-detail-view.tsx +225 -0
- package/src/components/playbook/playbook-homepage.tsx +142 -0
- package/src/components/playbook/playbook-toc.tsx +90 -0
- package/src/components/playbook/playbook-updated-badge.tsx +23 -0
- package/src/components/playbook/related-docs.tsx +30 -0
- package/src/components/profiles/__tests__/learned-context-panel.test.tsx +175 -0
- package/src/components/profiles/context-proposal-review.tsx +7 -3
- package/src/components/profiles/learned-context-panel.tsx +116 -8
- package/src/components/profiles/profile-browser.tsx +1 -0
- package/src/components/profiles/profile-card.tsx +16 -8
- package/src/components/profiles/profile-detail-view.tsx +12 -4
- package/src/components/settings/__tests__/auth-config-section.test.tsx +147 -0
- package/src/components/settings/api-key-form.tsx +5 -43
- package/src/components/settings/auth-config-section.tsx +10 -6
- package/src/components/settings/auth-status-badge.tsx +8 -0
- package/src/components/settings/budget-guardrails-section.tsx +403 -620
- package/src/components/settings/connection-test-control.tsx +63 -0
- package/src/components/settings/permissions-section.tsx +85 -75
- package/src/components/settings/permissions-sections.tsx +24 -0
- package/src/components/settings/presets-section.tsx +159 -0
- package/src/components/settings/pricing-registry-panel.tsx +164 -0
- package/src/components/shared/app-sidebar.tsx +4 -2
- package/src/components/shared/command-palette.tsx +30 -0
- package/src/components/shared/light-markdown.tsx +134 -0
- package/src/components/tasks/__tests__/kanban-board-accessibility.test.tsx +1 -1
- package/src/components/tasks/ai-assist-panel.tsx +108 -78
- package/src/components/tasks/content-preview.tsx +2 -1
- package/src/components/tasks/kanban-board.tsx +57 -5
- package/src/components/tasks/kanban-column.tsx +34 -23
- package/src/components/tasks/task-bento-cell.tsx +50 -0
- package/src/components/tasks/task-bento-grid.tsx +155 -0
- package/src/components/tasks/task-card.tsx +14 -16
- package/src/components/tasks/task-chip-bar.tsx +207 -0
- package/src/components/tasks/task-detail-view.tsx +42 -190
- package/src/components/tasks/task-result-renderer.tsx +33 -0
- package/src/components/workflows/blueprint-gallery.tsx +19 -12
- package/src/components/workflows/blueprint-preview.tsx +8 -1
- package/src/components/workflows/loop-status-view.tsx +2 -4
- package/src/components/workflows/swarm-dashboard.tsx +2 -3
- package/src/components/workflows/workflow-confirmation-view.tsx +2 -7
- package/src/components/workflows/workflow-full-output.tsx +80 -0
- package/src/components/workflows/workflow-kanban-card.tsx +121 -0
- package/src/components/workflows/workflow-list.tsx +47 -42
- package/src/components/workflows/workflow-status-view.tsx +163 -16
- package/src/lib/agents/learned-context.ts +27 -15
- package/src/lib/agents/learning-session.ts +354 -0
- package/src/lib/agents/pattern-extractor.ts +19 -0
- package/src/lib/agents/profiles/__tests__/sort.test.ts +42 -0
- package/src/lib/agents/profiles/sort.ts +7 -0
- package/src/lib/constants/card-icons.tsx +202 -0
- package/src/lib/constants/prose-styles.ts +7 -0
- package/src/lib/constants/settings.ts +1 -0
- package/src/lib/constants/task-status.ts +3 -0
- package/src/lib/db/schema.ts +3 -0
- package/src/lib/docs/adoption.ts +105 -0
- package/src/lib/docs/journey-tracker.ts +21 -0
- package/src/lib/docs/reader.ts +107 -0
- package/src/lib/docs/types.ts +54 -0
- package/src/lib/docs/usage-stage.ts +60 -0
- package/src/lib/documents/context-builder.ts +41 -0
- package/src/lib/notifications/actionable.ts +18 -10
- package/src/lib/queries/chart-data.ts +20 -1
- package/src/lib/settings/__tests__/budget-guardrails.test.ts +86 -24
- package/src/lib/settings/budget-guardrails.ts +213 -85
- package/src/lib/settings/permission-presets.ts +150 -0
- package/src/lib/settings/runtime-setup.ts +71 -0
- package/src/lib/usage/__tests__/ledger.test.ts +2 -2
- package/src/lib/usage/__tests__/pricing-registry.test.ts +78 -0
- package/src/lib/usage/ledger.ts +1 -1
- package/src/lib/usage/pricing-registry.ts +570 -0
- package/src/lib/usage/pricing.ts +15 -95
- package/src/lib/utils/__tests__/learned-context-history.test.ts +171 -0
- package/src/lib/utils/learned-context-history.ts +150 -0
- package/src/lib/validators/__tests__/settings.test.ts +23 -16
- package/src/lib/validators/settings.ts +3 -9
- package/src/lib/workflows/engine.ts +75 -61
- package/src/lib/workflows/types.ts +2 -0
- package/tsconfig.json +2 -1
- package/src/components/documents/document-preview.tsx +0 -68
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getRuntimeCatalogEntry,
|
|
3
|
+
SUPPORTED_AGENT_RUNTIMES,
|
|
4
|
+
type AgentRuntimeId,
|
|
5
|
+
} from "@/lib/agents/runtime/catalog";
|
|
6
|
+
import { getAuthSettings } from "./auth";
|
|
7
|
+
import { getOpenAIAuthSettings } from "./openai-auth";
|
|
8
|
+
import type { ApiKeySource, AuthMethod } from "@/lib/constants/settings";
|
|
9
|
+
|
|
10
|
+
export type RuntimeBillingMode = "usage" | "subscription";
|
|
11
|
+
export type RuntimeSetupMethod = AuthMethod | "none";
|
|
12
|
+
|
|
13
|
+
export interface RuntimeSetupState {
|
|
14
|
+
runtimeId: AgentRuntimeId;
|
|
15
|
+
label: string;
|
|
16
|
+
providerId: "anthropic" | "openai";
|
|
17
|
+
configured: boolean;
|
|
18
|
+
authMethod: RuntimeSetupMethod;
|
|
19
|
+
apiKeySource: ApiKeySource;
|
|
20
|
+
billingMode: RuntimeBillingMode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function getRuntimeSetupStates(): Promise<
|
|
24
|
+
Record<AgentRuntimeId, RuntimeSetupState>
|
|
25
|
+
> {
|
|
26
|
+
const [claudeAuth, openAIAuth] = await Promise.all([
|
|
27
|
+
getAuthSettings(),
|
|
28
|
+
getOpenAIAuthSettings(),
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
const claudeRuntime = getRuntimeCatalogEntry("claude-code");
|
|
32
|
+
const openAIRuntime = getRuntimeCatalogEntry("openai-codex-app-server");
|
|
33
|
+
|
|
34
|
+
const claudeAuthMethod: RuntimeSetupMethod =
|
|
35
|
+
claudeAuth.method === "oauth" || claudeAuth.apiKeySource === "oauth"
|
|
36
|
+
? "oauth"
|
|
37
|
+
: claudeAuth.hasKey
|
|
38
|
+
? "api_key"
|
|
39
|
+
: "none";
|
|
40
|
+
const claudeConfigured =
|
|
41
|
+
claudeAuth.hasKey || claudeAuth.apiKeySource === "oauth";
|
|
42
|
+
|
|
43
|
+
const states = {
|
|
44
|
+
"claude-code": {
|
|
45
|
+
runtimeId: "claude-code",
|
|
46
|
+
label: claudeRuntime.label,
|
|
47
|
+
providerId: claudeRuntime.providerId,
|
|
48
|
+
configured: claudeConfigured,
|
|
49
|
+
authMethod: claudeAuthMethod,
|
|
50
|
+
apiKeySource: claudeAuth.apiKeySource,
|
|
51
|
+
billingMode: claudeAuthMethod === "oauth" ? "subscription" : "usage",
|
|
52
|
+
},
|
|
53
|
+
"openai-codex-app-server": {
|
|
54
|
+
runtimeId: "openai-codex-app-server",
|
|
55
|
+
label: openAIRuntime.label,
|
|
56
|
+
providerId: openAIRuntime.providerId,
|
|
57
|
+
configured: openAIAuth.hasKey,
|
|
58
|
+
authMethod: openAIAuth.hasKey ? "api_key" : "none",
|
|
59
|
+
apiKeySource: openAIAuth.apiKeySource,
|
|
60
|
+
billingMode: "usage",
|
|
61
|
+
},
|
|
62
|
+
} satisfies Record<AgentRuntimeId, RuntimeSetupState>;
|
|
63
|
+
|
|
64
|
+
return states;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function listConfiguredRuntimeIds(
|
|
68
|
+
states: Record<AgentRuntimeId, RuntimeSetupState>
|
|
69
|
+
) {
|
|
70
|
+
return SUPPORTED_AGENT_RUNTIMES.filter((runtimeId) => states[runtimeId].configured);
|
|
71
|
+
}
|
|
@@ -85,13 +85,13 @@ describe("usage ledger", () => {
|
|
|
85
85
|
const priced = rows.find((row) => row.modelId === "claude-sonnet-4-20250514");
|
|
86
86
|
expect(priced?.costMicros).toBe(10_500);
|
|
87
87
|
expect(priced?.status).toBe("completed");
|
|
88
|
-
expect(priced?.pricingVersion).toBe("
|
|
88
|
+
expect(priced?.pricingVersion).toBe("anthropic-claude-sonnet");
|
|
89
89
|
|
|
90
90
|
// Unknown model: fallback pricing (conservative Opus-tier for OpenAI: $10/$30)
|
|
91
91
|
const fallback = rows.find((row) => row.modelId === "codex-unknown");
|
|
92
92
|
expect(fallback?.costMicros).toBeGreaterThan(0);
|
|
93
93
|
expect(fallback?.status).toBe("completed");
|
|
94
|
-
expect(fallback?.pricingVersion).toBe("
|
|
94
|
+
expect(fallback?.pricingVersion).toBe("openai-fallback");
|
|
95
95
|
|
|
96
96
|
// Null modelId: truly unknown
|
|
97
97
|
const unknown = rows.find((row) => row.modelId === null);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { tmpdir } from "os";
|
|
5
|
+
|
|
6
|
+
let tempDir: string;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tempDir = mkdtempSync(join(tmpdir(), "stagent-pricing-registry-"));
|
|
10
|
+
vi.resetModules();
|
|
11
|
+
vi.stubEnv("STAGENT_DATA_DIR", tempDir);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
vi.unstubAllEnvs();
|
|
16
|
+
vi.unstubAllGlobals();
|
|
17
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("pricing registry", () => {
|
|
21
|
+
it("refreshes pricing from official provider pages and updates visible rows", async () => {
|
|
22
|
+
const fetch = vi.fn(async (input: string) => {
|
|
23
|
+
if (input.includes("anthropic.com")) {
|
|
24
|
+
return new Response(`
|
|
25
|
+
<html>
|
|
26
|
+
<body>
|
|
27
|
+
Claude Sonnet 4 $3 / 1M input tokens $15 / 1M output tokens
|
|
28
|
+
Claude Opus 4 $15 / 1M input tokens $75 / 1M output tokens
|
|
29
|
+
Claude Haiku 3.5 $0.80 / 1M input tokens $4 / 1M output tokens
|
|
30
|
+
Claude Pro $20
|
|
31
|
+
Max 5x $100
|
|
32
|
+
Max 20x $200
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return new Response(`
|
|
39
|
+
<html>
|
|
40
|
+
<body>
|
|
41
|
+
GPT-5 $10 / 1M input tokens $30 / 1M output tokens
|
|
42
|
+
GPT-4o $2.50 / 1M input tokens $10 / 1M output tokens
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
45
|
+
`);
|
|
46
|
+
});
|
|
47
|
+
vi.stubGlobal("fetch", fetch);
|
|
48
|
+
|
|
49
|
+
const { refreshPricingRegistry } = await import("../pricing-registry");
|
|
50
|
+
const snapshot = await refreshPricingRegistry();
|
|
51
|
+
|
|
52
|
+
expect(snapshot.providers.anthropic.rows.find((row) => row.key === "anthropic-plan-pro")?.monthlyPriceUsd).toBe(20);
|
|
53
|
+
expect(snapshot.providers.anthropic.rows.find((row) => row.key === "anthropic-claude-sonnet")?.inputCostPerMillionMicros).toBe(3_000_000);
|
|
54
|
+
expect(snapshot.providers.openai.rows.find((row) => row.key === "openai-gpt-5")?.outputCostPerMillionMicros).toBe(30_000_000);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("keeps last-known-good pricing when a refresh fails", async () => {
|
|
58
|
+
const fetch = vi.fn(async (input: string) => {
|
|
59
|
+
if (input.includes("anthropic.com")) {
|
|
60
|
+
return new Response(`<html><body>Claude Pro $20</body></html>`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error("network down");
|
|
64
|
+
});
|
|
65
|
+
vi.stubGlobal("fetch", fetch);
|
|
66
|
+
|
|
67
|
+
const { refreshPricingRegistry, getPricingRegistrySnapshot } = await import(
|
|
68
|
+
"../pricing-registry"
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
await refreshPricingRegistry();
|
|
72
|
+
const snapshot = await getPricingRegistrySnapshot();
|
|
73
|
+
|
|
74
|
+
expect(snapshot.providers.anthropic.refreshError).toBeNull();
|
|
75
|
+
expect(snapshot.providers.openai.refreshError).toContain("network down");
|
|
76
|
+
expect(snapshot.providers.openai.rows.find((row) => row.key === "openai-gpt-5")?.inputCostPerMillionMicros).toBe(10_000_000);
|
|
77
|
+
});
|
|
78
|
+
});
|
package/src/lib/usage/ledger.ts
CHANGED
|
@@ -207,7 +207,7 @@ export async function recordUsageLedgerEntry(input: UsageLedgerWriteInput) {
|
|
|
207
207
|
(normalizedInputTokens != null && normalizedOutputTokens != null
|
|
208
208
|
? normalizedInputTokens + normalizedOutputTokens
|
|
209
209
|
: null);
|
|
210
|
-
const { costMicros, pricingVersion } = deriveUsageCostMicros({
|
|
210
|
+
const { costMicros, pricingVersion } = await deriveUsageCostMicros({
|
|
211
211
|
providerId: input.providerId,
|
|
212
212
|
modelId: input.modelId,
|
|
213
213
|
inputTokens: normalizedInputTokens,
|