stagent 0.1.0
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/LICENSE +191 -0
- package/README.md +399 -0
- package/components.json +21 -0
- package/dist/cli.js +171 -0
- package/drizzle.config.ts +12 -0
- package/next.config.mjs +15 -0
- package/package.json +114 -0
- package/postcss.config.mjs +8 -0
- package/public/icon-512.png +0 -0
- package/public/icon.svg +13 -0
- package/public/readme/home-workspace.png +0 -0
- package/public/readme/inbox-approvals.png +0 -0
- package/public/readme/workflow-blueprints.png +0 -0
- package/public/stagent-s-128.png +0 -0
- package/public/stagent-s-64.png +0 -0
- package/src/app/api/blueprints/[id]/instantiate/route.ts +27 -0
- package/src/app/api/blueprints/[id]/route.ts +39 -0
- package/src/app/api/blueprints/import/route.ts +68 -0
- package/src/app/api/blueprints/route.ts +29 -0
- package/src/app/api/command-palette/recent/route.ts +31 -0
- package/src/app/api/data/clear/route.ts +22 -0
- package/src/app/api/data/seed/route.ts +22 -0
- package/src/app/api/documents/[id]/file/route.ts +44 -0
- package/src/app/api/documents/[id]/route.ts +123 -0
- package/src/app/api/documents/route.ts +59 -0
- package/src/app/api/logs/stream/route.ts +101 -0
- package/src/app/api/notifications/[id]/route.ts +36 -0
- package/src/app/api/notifications/mark-all-read/route.ts +13 -0
- package/src/app/api/notifications/pending-approvals/route.ts +10 -0
- package/src/app/api/notifications/pending-approvals/stream/route.ts +101 -0
- package/src/app/api/notifications/route.ts +34 -0
- package/src/app/api/permissions/route.ts +46 -0
- package/src/app/api/profiles/[id]/route.ts +79 -0
- package/src/app/api/profiles/[id]/test/route.ts +42 -0
- package/src/app/api/profiles/import/route.ts +108 -0
- package/src/app/api/profiles/route.ts +50 -0
- package/src/app/api/projects/[id]/route.ts +72 -0
- package/src/app/api/projects/route.ts +53 -0
- package/src/app/api/schedules/[id]/route.ts +185 -0
- package/src/app/api/schedules/route.ts +117 -0
- package/src/app/api/settings/budgets/route.ts +24 -0
- package/src/app/api/settings/openai/route.ts +24 -0
- package/src/app/api/settings/route.ts +21 -0
- package/src/app/api/settings/test/route.ts +26 -0
- package/src/app/api/tasks/[id]/cancel/route.ts +21 -0
- package/src/app/api/tasks/[id]/execute/route.ts +90 -0
- package/src/app/api/tasks/[id]/logs/route.ts +95 -0
- package/src/app/api/tasks/[id]/output/route.ts +47 -0
- package/src/app/api/tasks/[id]/respond/route.ts +64 -0
- package/src/app/api/tasks/[id]/resume/route.ts +76 -0
- package/src/app/api/tasks/[id]/route.ts +77 -0
- package/src/app/api/tasks/assist/route.ts +35 -0
- package/src/app/api/tasks/route.ts +82 -0
- package/src/app/api/uploads/[id]/route.ts +81 -0
- package/src/app/api/uploads/cleanup/route.ts +7 -0
- package/src/app/api/uploads/route.ts +66 -0
- package/src/app/api/workflows/[id]/execute/route.ts +82 -0
- package/src/app/api/workflows/[id]/route.ts +133 -0
- package/src/app/api/workflows/[id]/status/route.ts +54 -0
- package/src/app/api/workflows/[id]/steps/[stepId]/retry/route.ts +22 -0
- package/src/app/api/workflows/route.ts +61 -0
- package/src/app/apple-icon.tsx +31 -0
- package/src/app/costs/page.tsx +256 -0
- package/src/app/dashboard/page.tsx +44 -0
- package/src/app/documents/[id]/page.tsx +46 -0
- package/src/app/documents/page.tsx +45 -0
- package/src/app/error.tsx +26 -0
- package/src/app/global-error.tsx +23 -0
- package/src/app/globals.css +733 -0
- package/src/app/icon.tsx +30 -0
- package/src/app/inbox/loading.tsx +15 -0
- package/src/app/inbox/page.tsx +35 -0
- package/src/app/layout.tsx +78 -0
- package/src/app/manifest.ts +32 -0
- package/src/app/monitor/page.tsx +37 -0
- package/src/app/page.tsx +162 -0
- package/src/app/profiles/[id]/edit/page.tsx +39 -0
- package/src/app/profiles/[id]/page.tsx +33 -0
- package/src/app/profiles/new/page.tsx +22 -0
- package/src/app/profiles/page.tsx +19 -0
- package/src/app/projects/[id]/page.tsx +134 -0
- package/src/app/projects/loading.tsx +17 -0
- package/src/app/projects/page.tsx +32 -0
- package/src/app/schedules/[id]/page.tsx +47 -0
- package/src/app/schedules/page.tsx +18 -0
- package/src/app/settings/loading.tsx +24 -0
- package/src/app/settings/page.tsx +27 -0
- package/src/app/tasks/[id]/page.tsx +45 -0
- package/src/app/tasks/new/page.tsx +27 -0
- package/src/app/workflows/[id]/edit/page.tsx +66 -0
- package/src/app/workflows/[id]/page.tsx +37 -0
- package/src/app/workflows/blueprints/[id]/page.tsx +40 -0
- package/src/app/workflows/blueprints/new/page.tsx +20 -0
- package/src/app/workflows/blueprints/page.tsx +11 -0
- package/src/app/workflows/new/page.tsx +36 -0
- package/src/app/workflows/page.tsx +18 -0
- package/src/components/charts/donut-ring.tsx +64 -0
- package/src/components/charts/mini-bar.tsx +75 -0
- package/src/components/charts/sparkline.tsx +107 -0
- package/src/components/costs/cost-dashboard.tsx +877 -0
- package/src/components/costs/cost-filters.tsx +179 -0
- package/src/components/dashboard/activity-feed.tsx +95 -0
- package/src/components/dashboard/greeting.tsx +30 -0
- package/src/components/dashboard/priority-queue.tsx +79 -0
- package/src/components/dashboard/quick-actions.tsx +62 -0
- package/src/components/dashboard/recent-projects.tsx +79 -0
- package/src/components/dashboard/stats-cards.tsx +114 -0
- package/src/components/documents/document-browser.tsx +235 -0
- package/src/components/documents/document-detail-view.tsx +367 -0
- package/src/components/documents/document-grid.tsx +78 -0
- package/src/components/documents/document-preview.tsx +68 -0
- package/src/components/documents/document-table.tsx +119 -0
- package/src/components/documents/document-upload-dialog.tsx +153 -0
- package/src/components/documents/types.ts +6 -0
- package/src/components/documents/utils.ts +57 -0
- package/src/components/monitoring/connection-indicator.tsx +14 -0
- package/src/components/monitoring/log-entry.tsx +79 -0
- package/src/components/monitoring/log-filters.tsx +57 -0
- package/src/components/monitoring/log-stream.tsx +144 -0
- package/src/components/monitoring/monitor-overview-wrapper.tsx +64 -0
- package/src/components/monitoring/monitor-overview.tsx +119 -0
- package/src/components/notifications/failure-action.tsx +38 -0
- package/src/components/notifications/inbox-list.tsx +165 -0
- package/src/components/notifications/message-response.tsx +196 -0
- package/src/components/notifications/notification-item.tsx +250 -0
- package/src/components/notifications/pending-approval-host.tsx +478 -0
- package/src/components/notifications/permission-action.tsx +37 -0
- package/src/components/notifications/permission-response-actions.tsx +126 -0
- package/src/components/notifications/unread-badge.tsx +35 -0
- package/src/components/profiles/profile-browser.tsx +117 -0
- package/src/components/profiles/profile-card.tsx +78 -0
- package/src/components/profiles/profile-detail-view.tsx +564 -0
- package/src/components/profiles/profile-form-view.tsx +480 -0
- package/src/components/profiles/profile-import-dialog.tsx +113 -0
- package/src/components/projects/project-card.tsx +58 -0
- package/src/components/projects/project-create-dialog.tsx +140 -0
- package/src/components/projects/project-detail.tsx +68 -0
- package/src/components/projects/project-edit-dialog.tsx +219 -0
- package/src/components/projects/project-list.tsx +108 -0
- package/src/components/schedules/schedule-create-dialog.tsx +403 -0
- package/src/components/schedules/schedule-detail-view.tsx +274 -0
- package/src/components/schedules/schedule-list.tsx +242 -0
- package/src/components/schedules/schedule-status-badge.tsx +16 -0
- package/src/components/settings/api-key-form.tsx +141 -0
- package/src/components/settings/auth-config-section.tsx +141 -0
- package/src/components/settings/auth-method-selector.tsx +67 -0
- package/src/components/settings/auth-status-badge.tsx +40 -0
- package/src/components/settings/auth-status-dot.tsx +59 -0
- package/src/components/settings/budget-guardrails-section.tsx +842 -0
- package/src/components/settings/data-management-section.tsx +141 -0
- package/src/components/settings/openai-runtime-section.tsx +104 -0
- package/src/components/settings/permissions-section.tsx +91 -0
- package/src/components/shared/app-sidebar.tsx +123 -0
- package/src/components/shared/card-skeleton.tsx +42 -0
- package/src/components/shared/command-palette.tsx +250 -0
- package/src/components/shared/confirm-dialog.tsx +52 -0
- package/src/components/shared/empty-state.tsx +24 -0
- package/src/components/shared/error-state.tsx +32 -0
- package/src/components/shared/form-section-card.tsx +33 -0
- package/src/components/shared/section-heading.tsx +14 -0
- package/src/components/shared/stagent-logo.tsx +21 -0
- package/src/components/shared/theme-toggle.tsx +46 -0
- package/src/components/tasks/ai-assist-panel.tsx +210 -0
- package/src/components/tasks/content-preview.tsx +89 -0
- package/src/components/tasks/empty-board.tsx +12 -0
- package/src/components/tasks/file-upload.tsx +120 -0
- package/src/components/tasks/kanban-board.tsx +275 -0
- package/src/components/tasks/kanban-column.tsx +75 -0
- package/src/components/tasks/skeleton-board.tsx +21 -0
- package/src/components/tasks/task-attachments.tsx +114 -0
- package/src/components/tasks/task-card.tsx +101 -0
- package/src/components/tasks/task-create-panel.tsx +360 -0
- package/src/components/tasks/task-detail-view.tsx +356 -0
- package/src/components/ui/alert-dialog.tsx +196 -0
- package/src/components/ui/badge.tsx +50 -0
- package/src/components/ui/button.tsx +71 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/checkbox.tsx +32 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/dialog.tsx +158 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/form.tsx +167 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/popover.tsx +89 -0
- package/src/components/ui/progress.tsx +31 -0
- package/src/components/ui/radio-group.tsx +45 -0
- package/src/components/ui/scroll-area.tsx +58 -0
- package/src/components/ui/select.tsx +190 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +143 -0
- package/src/components/ui/sidebar.tsx +726 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +63 -0
- package/src/components/ui/sonner.tsx +36 -0
- package/src/components/ui/switch.tsx +35 -0
- package/src/components/ui/table.tsx +116 -0
- package/src/components/ui/tabs.tsx +91 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +57 -0
- package/src/components/workflows/blueprint-editor.tsx +109 -0
- package/src/components/workflows/blueprint-gallery.tsx +155 -0
- package/src/components/workflows/blueprint-preview.tsx +240 -0
- package/src/components/workflows/loop-status-view.tsx +272 -0
- package/src/components/workflows/swarm-dashboard.tsx +185 -0
- package/src/components/workflows/workflow-form-view.tsx +1376 -0
- package/src/components/workflows/workflow-list.tsx +230 -0
- package/src/components/workflows/workflow-status-view.tsx +477 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/instrumentation.ts +7 -0
- package/src/lib/agents/claude-agent.ts +737 -0
- package/src/lib/agents/execution-manager.ts +27 -0
- package/src/lib/agents/profiles/assignment-validation.ts +75 -0
- package/src/lib/agents/profiles/builtins/code-reviewer/SKILL.md +21 -0
- package/src/lib/agents/profiles/builtins/code-reviewer/profile.yaml +28 -0
- package/src/lib/agents/profiles/builtins/data-analyst/SKILL.md +25 -0
- package/src/lib/agents/profiles/builtins/data-analyst/profile.yaml +27 -0
- package/src/lib/agents/profiles/builtins/devops-engineer/SKILL.md +34 -0
- package/src/lib/agents/profiles/builtins/devops-engineer/profile.yaml +27 -0
- package/src/lib/agents/profiles/builtins/document-writer/SKILL.md +16 -0
- package/src/lib/agents/profiles/builtins/document-writer/profile.yaml +27 -0
- package/src/lib/agents/profiles/builtins/general/SKILL.md +13 -0
- package/src/lib/agents/profiles/builtins/general/profile.yaml +18 -0
- package/src/lib/agents/profiles/builtins/health-fitness-coach/SKILL.md +34 -0
- package/src/lib/agents/profiles/builtins/health-fitness-coach/profile.yaml +26 -0
- package/src/lib/agents/profiles/builtins/learning-coach/SKILL.md +35 -0
- package/src/lib/agents/profiles/builtins/learning-coach/profile.yaml +26 -0
- package/src/lib/agents/profiles/builtins/project-manager/SKILL.md +26 -0
- package/src/lib/agents/profiles/builtins/project-manager/profile.yaml +26 -0
- package/src/lib/agents/profiles/builtins/researcher/SKILL.md +15 -0
- package/src/lib/agents/profiles/builtins/researcher/profile.yaml +27 -0
- package/src/lib/agents/profiles/builtins/shopping-assistant/SKILL.md +34 -0
- package/src/lib/agents/profiles/builtins/shopping-assistant/profile.yaml +26 -0
- package/src/lib/agents/profiles/builtins/technical-writer/SKILL.md +31 -0
- package/src/lib/agents/profiles/builtins/technical-writer/profile.yaml +29 -0
- package/src/lib/agents/profiles/builtins/travel-planner/SKILL.md +23 -0
- package/src/lib/agents/profiles/builtins/travel-planner/profile.yaml +26 -0
- package/src/lib/agents/profiles/builtins/wealth-manager/SKILL.md +24 -0
- package/src/lib/agents/profiles/builtins/wealth-manager/profile.yaml +26 -0
- package/src/lib/agents/profiles/compatibility.ts +109 -0
- package/src/lib/agents/profiles/registry.ts +293 -0
- package/src/lib/agents/profiles/test-runner.ts +18 -0
- package/src/lib/agents/profiles/test-types.ts +20 -0
- package/src/lib/agents/profiles/types.ts +43 -0
- package/src/lib/agents/router.ts +56 -0
- package/src/lib/agents/runtime/catalog.ts +85 -0
- package/src/lib/agents/runtime/claude-sdk.ts +12 -0
- package/src/lib/agents/runtime/claude.ts +370 -0
- package/src/lib/agents/runtime/codex-app-server-client.ts +289 -0
- package/src/lib/agents/runtime/index.ts +167 -0
- package/src/lib/agents/runtime/openai-codex.ts +1089 -0
- package/src/lib/agents/runtime/task-assist-types.ts +8 -0
- package/src/lib/agents/runtime/types.ts +30 -0
- package/src/lib/constants/settings.ts +13 -0
- package/src/lib/constants/status-colors.ts +44 -0
- package/src/lib/constants/task-status.ts +49 -0
- package/src/lib/data/clear.ts +63 -0
- package/src/lib/data/seed-data/documents.ts +715 -0
- package/src/lib/data/seed-data/logs.ts +195 -0
- package/src/lib/data/seed-data/notifications.ts +141 -0
- package/src/lib/data/seed-data/profiles.ts +175 -0
- package/src/lib/data/seed-data/projects.ts +61 -0
- package/src/lib/data/seed-data/schedules.ts +108 -0
- package/src/lib/data/seed-data/tasks.ts +341 -0
- package/src/lib/data/seed-data/usage-ledger.ts +130 -0
- package/src/lib/data/seed-data/workflows.ts +213 -0
- package/src/lib/data/seed.ts +129 -0
- package/src/lib/db/index.ts +221 -0
- package/src/lib/db/migrations/0000_aromatic_gargoyle.sql +59 -0
- package/src/lib/db/migrations/0001_first_iron_patriot.sql +6 -0
- package/src/lib/db/migrations/0002_add_resume_count.sql +1 -0
- package/src/lib/db/migrations/0003_add_settings.sql +5 -0
- package/src/lib/db/migrations/0004_add_documents.sql +20 -0
- package/src/lib/db/migrations/0005_add_document_preprocessing.sql +4 -0
- package/src/lib/db/migrations/0006_add_agent_profile.sql +2 -0
- package/src/lib/db/migrations/0007_add_usage_metering_ledger.sql +30 -0
- package/src/lib/db/migrations/0008_add_document_version.sql +1 -0
- package/src/lib/db/migrations/meta/0000_snapshot.json +416 -0
- package/src/lib/db/migrations/meta/0001_snapshot.json +461 -0
- package/src/lib/db/migrations/meta/0002_snapshot.json +469 -0
- package/src/lib/db/migrations/meta/_journal.json +27 -0
- package/src/lib/db/schema.ts +227 -0
- package/src/lib/documents/cleanup.ts +50 -0
- package/src/lib/documents/context-builder.ts +75 -0
- package/src/lib/documents/output-scanner.ts +166 -0
- package/src/lib/documents/processor.ts +120 -0
- package/src/lib/documents/processors/image.ts +21 -0
- package/src/lib/documents/processors/office.ts +36 -0
- package/src/lib/documents/processors/pdf.ts +12 -0
- package/src/lib/documents/processors/spreadsheet.ts +18 -0
- package/src/lib/documents/processors/text.ts +8 -0
- package/src/lib/documents/registry.ts +25 -0
- package/src/lib/notifications/actionable.ts +108 -0
- package/src/lib/notifications/permissions.ts +169 -0
- package/src/lib/queries/chart-data.ts +184 -0
- package/src/lib/schedules/interval-parser.ts +110 -0
- package/src/lib/schedules/scheduler.ts +220 -0
- package/src/lib/settings/auth.ts +98 -0
- package/src/lib/settings/budget-guardrails.ts +590 -0
- package/src/lib/settings/helpers.ts +23 -0
- package/src/lib/settings/openai-auth.ts +80 -0
- package/src/lib/settings/permissions.ts +102 -0
- package/src/lib/usage/ledger.ts +489 -0
- package/src/lib/usage/pricing.ts +68 -0
- package/src/lib/utils/crypto.ts +90 -0
- package/src/lib/utils/format-timestamp.ts +46 -0
- package/src/lib/utils/session-cleanup.ts +26 -0
- package/src/lib/utils/stagent-paths.ts +18 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/validators/blueprint.ts +43 -0
- package/src/lib/validators/profile.ts +64 -0
- package/src/lib/validators/project.ts +17 -0
- package/src/lib/validators/settings.ts +57 -0
- package/src/lib/validators/task.ts +30 -0
- package/src/lib/workflows/blueprints/builtins/code-review-pipeline.yaml +72 -0
- package/src/lib/workflows/blueprints/builtins/documentation-generation.yaml +62 -0
- package/src/lib/workflows/blueprints/builtins/investment-research.yaml +81 -0
- package/src/lib/workflows/blueprints/builtins/meal-planning.yaml +73 -0
- package/src/lib/workflows/blueprints/builtins/product-research.yaml +72 -0
- package/src/lib/workflows/blueprints/builtins/research-report.yaml +77 -0
- package/src/lib/workflows/blueprints/builtins/sprint-planning.yaml +77 -0
- package/src/lib/workflows/blueprints/builtins/travel-planning.yaml +80 -0
- package/src/lib/workflows/blueprints/instantiator.ts +131 -0
- package/src/lib/workflows/blueprints/registry.ts +128 -0
- package/src/lib/workflows/blueprints/template.ts +58 -0
- package/src/lib/workflows/blueprints/types.ts +38 -0
- package/src/lib/workflows/definition-validation.ts +121 -0
- package/src/lib/workflows/engine.ts +1113 -0
- package/src/lib/workflows/loop-executor.ts +270 -0
- package/src/lib/workflows/parallel.ts +55 -0
- package/src/lib/workflows/swarm.ts +97 -0
- package/src/lib/workflows/types.ts +112 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { randomBytes, createCipheriv, createDecipheriv } from "crypto";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
|
|
6
|
+
const ALGORITHM = "aes-256-gcm";
|
|
7
|
+
const IV_LENGTH = 12;
|
|
8
|
+
const AUTH_TAG_LENGTH = 16;
|
|
9
|
+
const KEY_LENGTH = 32;
|
|
10
|
+
|
|
11
|
+
function getKeyfilePath(): string {
|
|
12
|
+
return join(
|
|
13
|
+
process.env.STAGENT_DATA_DIR || join(homedir(), ".stagent"),
|
|
14
|
+
".keyfile"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Read or create the encryption keyfile at ~/.stagent/.keyfile.
|
|
20
|
+
* File is 32 random bytes with chmod 0600 (owner-only read/write).
|
|
21
|
+
*/
|
|
22
|
+
export function getOrCreateKeyfile(): Buffer {
|
|
23
|
+
const keyfilePath = getKeyfilePath();
|
|
24
|
+
|
|
25
|
+
if (existsSync(keyfilePath)) {
|
|
26
|
+
const key = readFileSync(keyfilePath);
|
|
27
|
+
if (key.length !== KEY_LENGTH) {
|
|
28
|
+
throw new Error(`Invalid keyfile: expected ${KEY_LENGTH} bytes, got ${key.length}`);
|
|
29
|
+
}
|
|
30
|
+
return key;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Create parent directory if needed
|
|
34
|
+
const dir = join(keyfilePath, "..");
|
|
35
|
+
mkdirSync(dir, { recursive: true });
|
|
36
|
+
|
|
37
|
+
const key = randomBytes(KEY_LENGTH);
|
|
38
|
+
writeFileSync(keyfilePath, key, { mode: 0o600 });
|
|
39
|
+
chmodSync(keyfilePath, 0o600);
|
|
40
|
+
return key;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Encrypt plaintext using AES-256-GCM.
|
|
45
|
+
* Returns base64 string in format: iv:authTag:ciphertext
|
|
46
|
+
*/
|
|
47
|
+
export function encrypt(plaintext: string): string {
|
|
48
|
+
const key = getOrCreateKeyfile();
|
|
49
|
+
const iv = randomBytes(IV_LENGTH);
|
|
50
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
51
|
+
|
|
52
|
+
const encrypted = Buffer.concat([
|
|
53
|
+
cipher.update(plaintext, "utf8"),
|
|
54
|
+
cipher.final(),
|
|
55
|
+
]);
|
|
56
|
+
const authTag = cipher.getAuthTag();
|
|
57
|
+
|
|
58
|
+
return [
|
|
59
|
+
iv.toString("base64"),
|
|
60
|
+
authTag.toString("base64"),
|
|
61
|
+
encrypted.toString("base64"),
|
|
62
|
+
].join(":");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Decrypt a string previously encrypted with encrypt().
|
|
67
|
+
* Expects base64 format: iv:authTag:ciphertext
|
|
68
|
+
*/
|
|
69
|
+
export function decrypt(encrypted: string): string {
|
|
70
|
+
const parts = encrypted.split(":");
|
|
71
|
+
if (parts.length !== 3) {
|
|
72
|
+
throw new Error("Invalid encrypted format: expected iv:authTag:ciphertext");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const [ivB64, authTagB64, ciphertextB64] = parts;
|
|
76
|
+
const key = getOrCreateKeyfile();
|
|
77
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
78
|
+
const authTag = Buffer.from(authTagB64, "base64");
|
|
79
|
+
const ciphertext = Buffer.from(ciphertextB64, "base64");
|
|
80
|
+
|
|
81
|
+
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
82
|
+
decipher.setAuthTag(authTag);
|
|
83
|
+
|
|
84
|
+
const decrypted = Buffer.concat([
|
|
85
|
+
decipher.update(ciphertext),
|
|
86
|
+
decipher.final(),
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
return decrypted.toString("utf8");
|
|
90
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const MINUTE = 60_000;
|
|
2
|
+
const HOUR = 3_600_000;
|
|
3
|
+
const DAY = 86_400_000;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Formats a timestamp with relative time for recent items
|
|
7
|
+
* and a full date for older ones.
|
|
8
|
+
*/
|
|
9
|
+
export function formatTimestamp(date: string | Date): string {
|
|
10
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
const diff = now - d.getTime();
|
|
13
|
+
|
|
14
|
+
if (diff < MINUTE) return "just now";
|
|
15
|
+
if (diff < HOUR) {
|
|
16
|
+
const mins = Math.floor(diff / MINUTE);
|
|
17
|
+
return `${mins}m ago`;
|
|
18
|
+
}
|
|
19
|
+
if (diff < DAY) {
|
|
20
|
+
const hours = Math.floor(diff / HOUR);
|
|
21
|
+
return `${hours}h ago`;
|
|
22
|
+
}
|
|
23
|
+
if (diff < 7 * DAY) {
|
|
24
|
+
const days = Math.floor(diff / DAY);
|
|
25
|
+
return `${days}d ago`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return d.toLocaleDateString("en-US", {
|
|
29
|
+
month: "short",
|
|
30
|
+
day: "numeric",
|
|
31
|
+
year: d.getFullYear() !== new Date().getFullYear() ? "numeric" : undefined,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Formats a timestamp as HH:MM:SS for log entries.
|
|
37
|
+
*/
|
|
38
|
+
export function formatTime(date: string | Date): string {
|
|
39
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
40
|
+
return d.toLocaleTimeString("en-US", {
|
|
41
|
+
hour12: false,
|
|
42
|
+
hour: "2-digit",
|
|
43
|
+
minute: "2-digit",
|
|
44
|
+
second: "2-digit",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { db } from "@/lib/db";
|
|
2
|
+
import { tasks } from "@/lib/db/schema";
|
|
3
|
+
import { eq, and, lt, isNotNull, inArray } from "drizzle-orm";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Nullify sessionId on completed/failed tasks older than retention period.
|
|
7
|
+
* Manual utility — not auto-scheduled.
|
|
8
|
+
*/
|
|
9
|
+
export function cleanupOldSessions(retentionDays = 7): number {
|
|
10
|
+
const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000);
|
|
11
|
+
|
|
12
|
+
const result = db
|
|
13
|
+
.update(tasks)
|
|
14
|
+
.set({ sessionId: null })
|
|
15
|
+
.where(
|
|
16
|
+
and(
|
|
17
|
+
isNotNull(tasks.sessionId),
|
|
18
|
+
inArray(tasks.status, ["completed", "failed"]),
|
|
19
|
+
lt(tasks.updatedAt, cutoff)
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
.returning()
|
|
23
|
+
.all();
|
|
24
|
+
|
|
25
|
+
return result.length;
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
|
|
4
|
+
export function getStagentDataDir(): string {
|
|
5
|
+
return process.env.STAGENT_DATA_DIR || join(homedir(), ".stagent");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getStagentDbPath(): string {
|
|
9
|
+
return join(getStagentDataDir(), "stagent.db");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getStagentUploadsDir(): string {
|
|
13
|
+
return join(getStagentDataDir(), "uploads");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getStagentBlueprintsDir(): string {
|
|
17
|
+
return join(getStagentDataDir(), "blueprints");
|
|
18
|
+
}
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const BlueprintVariableSchema = z.object({
|
|
4
|
+
id: z.string(),
|
|
5
|
+
type: z.enum(["text", "textarea", "select", "number", "boolean", "file"]),
|
|
6
|
+
label: z.string(),
|
|
7
|
+
description: z.string().optional(),
|
|
8
|
+
required: z.boolean(),
|
|
9
|
+
default: z.unknown().optional(),
|
|
10
|
+
placeholder: z.string().optional(),
|
|
11
|
+
options: z
|
|
12
|
+
.array(z.object({ value: z.string(), label: z.string() }))
|
|
13
|
+
.optional(),
|
|
14
|
+
min: z.number().optional(),
|
|
15
|
+
max: z.number().optional(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const BlueprintStepSchema = z.object({
|
|
19
|
+
name: z.string(),
|
|
20
|
+
profileId: z.string(),
|
|
21
|
+
promptTemplate: z.string(),
|
|
22
|
+
requiresApproval: z.boolean(),
|
|
23
|
+
expectedOutput: z.string().optional(),
|
|
24
|
+
condition: z.string().optional(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const BlueprintSchema = z.object({
|
|
28
|
+
id: z.string(),
|
|
29
|
+
name: z.string(),
|
|
30
|
+
description: z.string(),
|
|
31
|
+
version: z.string().regex(/^\d+\.\d+\.\d+$/),
|
|
32
|
+
domain: z.enum(["work", "personal"]),
|
|
33
|
+
tags: z.array(z.string()),
|
|
34
|
+
pattern: z.enum(["sequence", "planner-executor", "checkpoint"]),
|
|
35
|
+
variables: z.array(BlueprintVariableSchema),
|
|
36
|
+
steps: z.array(BlueprintStepSchema).min(1),
|
|
37
|
+
author: z.string().optional(),
|
|
38
|
+
source: z.string().url().optional(),
|
|
39
|
+
estimatedDuration: z.string().optional(),
|
|
40
|
+
difficulty: z.enum(["beginner", "intermediate", "advanced"]).optional(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export type BlueprintConfig = z.infer<typeof BlueprintSchema>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SUPPORTED_AGENT_RUNTIMES } from "@/lib/agents/runtime/catalog";
|
|
3
|
+
|
|
4
|
+
const runtimeIdSchema = z.enum(SUPPORTED_AGENT_RUNTIMES);
|
|
5
|
+
|
|
6
|
+
const profileTestsSchema = z.array(
|
|
7
|
+
z.object({
|
|
8
|
+
task: z.string(),
|
|
9
|
+
expectedKeywords: z.array(z.string()),
|
|
10
|
+
})
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const canUseToolPolicySchema = z.object({
|
|
14
|
+
autoApprove: z.array(z.string()).optional(),
|
|
15
|
+
autoDeny: z.array(z.string()).optional(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const profileRuntimeOverrideSchema = z.object({
|
|
19
|
+
instructions: z.string().min(1).optional(),
|
|
20
|
+
allowedTools: z.array(z.string()).optional(),
|
|
21
|
+
mcpServers: z.record(z.string(), z.unknown()).optional(),
|
|
22
|
+
canUseToolPolicy: canUseToolPolicySchema.optional(),
|
|
23
|
+
tests: profileTestsSchema.optional(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const ProfileConfigSchema = z.object({
|
|
27
|
+
id: z.string().min(1),
|
|
28
|
+
name: z.string().min(1),
|
|
29
|
+
version: z.string().regex(/^\d+\.\d+\.\d+$/),
|
|
30
|
+
domain: z.enum(["work", "personal"]),
|
|
31
|
+
tags: z.array(z.string()),
|
|
32
|
+
allowedTools: z.array(z.string()).optional(),
|
|
33
|
+
mcpServers: z.record(z.string(), z.unknown()).optional(),
|
|
34
|
+
canUseToolPolicy: canUseToolPolicySchema.optional(),
|
|
35
|
+
hooks: z
|
|
36
|
+
.object({
|
|
37
|
+
preToolCall: z.array(z.string()).optional(),
|
|
38
|
+
postToolCall: z.array(z.string()).optional(),
|
|
39
|
+
})
|
|
40
|
+
.optional(),
|
|
41
|
+
temperature: z.number().min(0).max(1).optional(),
|
|
42
|
+
maxTurns: z.number().positive().optional(),
|
|
43
|
+
outputFormat: z.string().optional(),
|
|
44
|
+
author: z.string().optional(),
|
|
45
|
+
source: z.string().url().optional(),
|
|
46
|
+
tests: profileTestsSchema.optional(),
|
|
47
|
+
supportedRuntimes: z.array(runtimeIdSchema).optional(),
|
|
48
|
+
runtimeOverrides: z
|
|
49
|
+
.object(
|
|
50
|
+
Object.fromEntries(
|
|
51
|
+
SUPPORTED_AGENT_RUNTIMES.map((runtimeId) => [
|
|
52
|
+
runtimeId,
|
|
53
|
+
profileRuntimeOverrideSchema.optional(),
|
|
54
|
+
])
|
|
55
|
+
) as Record<
|
|
56
|
+
(typeof SUPPORTED_AGENT_RUNTIMES)[number],
|
|
57
|
+
z.ZodOptional<typeof profileRuntimeOverrideSchema>
|
|
58
|
+
>
|
|
59
|
+
)
|
|
60
|
+
.partial()
|
|
61
|
+
.optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export type ProfileConfig = z.infer<typeof ProfileConfigSchema>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const createProjectSchema = z.object({
|
|
4
|
+
name: z.string().min(1, "Name is required").max(100),
|
|
5
|
+
description: z.string().max(500).optional(),
|
|
6
|
+
workingDirectory: z.string().max(500).optional(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const updateProjectSchema = z.object({
|
|
10
|
+
name: z.string().min(1).max(100).optional(),
|
|
11
|
+
description: z.string().max(500).optional(),
|
|
12
|
+
workingDirectory: z.string().max(500).optional(),
|
|
13
|
+
status: z.enum(["active", "paused", "completed"]).optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type CreateProjectInput = z.infer<typeof createProjectSchema>;
|
|
17
|
+
export type UpdateProjectInput = z.infer<typeof updateProjectSchema>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SUPPORTED_AGENT_RUNTIMES } from "@/lib/agents/runtime/catalog";
|
|
3
|
+
|
|
4
|
+
export const updateAuthSettingsSchema = z.object({
|
|
5
|
+
method: z.enum(["api_key", "oauth"]),
|
|
6
|
+
apiKey: z
|
|
7
|
+
.string()
|
|
8
|
+
.startsWith("sk-ant-", "API key must start with sk-ant-")
|
|
9
|
+
.optional(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export type UpdateAuthSettingsInput = z.infer<typeof updateAuthSettingsSchema>;
|
|
13
|
+
|
|
14
|
+
export const updateOpenAISettingsSchema = z.object({
|
|
15
|
+
apiKey: z
|
|
16
|
+
.string()
|
|
17
|
+
.startsWith("sk-", "API key must start with sk-"),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export type UpdateOpenAISettingsInput = z.infer<typeof updateOpenAISettingsSchema>;
|
|
21
|
+
|
|
22
|
+
const nullablePositiveNumber = z.preprocess((value) => {
|
|
23
|
+
if (value === "" || value == null) return null;
|
|
24
|
+
if (typeof value === "string") return Number(value);
|
|
25
|
+
return value;
|
|
26
|
+
}, z.number().finite().positive().nullable());
|
|
27
|
+
|
|
28
|
+
const nullablePositiveInteger = z.preprocess((value) => {
|
|
29
|
+
if (value === "" || value == null) return null;
|
|
30
|
+
if (typeof value === "string") return Number(value);
|
|
31
|
+
return value;
|
|
32
|
+
}, z.number().int().positive().nullable());
|
|
33
|
+
|
|
34
|
+
export const runtimeBudgetPolicySchema = z.object({
|
|
35
|
+
dailySpendCapUsd: nullablePositiveNumber,
|
|
36
|
+
monthlySpendCapUsd: nullablePositiveNumber,
|
|
37
|
+
dailyTokenCap: nullablePositiveInteger,
|
|
38
|
+
monthlyTokenCap: nullablePositiveInteger,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const budgetPolicySchema = z.object({
|
|
42
|
+
overall: z.object({
|
|
43
|
+
dailySpendCapUsd: nullablePositiveNumber,
|
|
44
|
+
monthlySpendCapUsd: nullablePositiveNumber,
|
|
45
|
+
}),
|
|
46
|
+
runtimes: z.object(
|
|
47
|
+
Object.fromEntries(
|
|
48
|
+
SUPPORTED_AGENT_RUNTIMES.map((runtimeId) => [runtimeId, runtimeBudgetPolicySchema])
|
|
49
|
+
) as Record<(typeof SUPPORTED_AGENT_RUNTIMES)[number], typeof runtimeBudgetPolicySchema>
|
|
50
|
+
),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const updateBudgetPolicySchema = budgetPolicySchema;
|
|
54
|
+
|
|
55
|
+
export type RuntimeBudgetPolicy = z.infer<typeof runtimeBudgetPolicySchema>;
|
|
56
|
+
export type BudgetPolicy = z.infer<typeof budgetPolicySchema>;
|
|
57
|
+
export type UpdateBudgetPolicyInput = z.infer<typeof updateBudgetPolicySchema>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SUPPORTED_AGENT_RUNTIMES } from "@/lib/agents/runtime/catalog";
|
|
3
|
+
|
|
4
|
+
const assignedAgentSchema = z.enum(SUPPORTED_AGENT_RUNTIMES);
|
|
5
|
+
|
|
6
|
+
export const createTaskSchema = z.object({
|
|
7
|
+
title: z.string().min(1, "Title is required").max(200),
|
|
8
|
+
description: z.string().max(2000).optional(),
|
|
9
|
+
projectId: z.string().optional(),
|
|
10
|
+
priority: z.number().min(0).max(3).default(2),
|
|
11
|
+
assignedAgent: assignedAgentSchema.optional(),
|
|
12
|
+
agentProfile: z.string().optional(),
|
|
13
|
+
fileIds: z.array(z.string()).optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const updateTaskSchema = z.object({
|
|
17
|
+
title: z.string().min(1).max(200).optional(),
|
|
18
|
+
description: z.string().max(2000).optional(),
|
|
19
|
+
status: z
|
|
20
|
+
.enum(["planned", "queued", "running", "completed", "failed", "cancelled"])
|
|
21
|
+
.optional(),
|
|
22
|
+
priority: z.number().min(0).max(3).optional(),
|
|
23
|
+
assignedAgent: assignedAgentSchema.optional(),
|
|
24
|
+
agentProfile: z.string().optional(),
|
|
25
|
+
result: z.string().optional(),
|
|
26
|
+
sessionId: z.string().optional(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export type CreateTaskInput = z.infer<typeof createTaskSchema>;
|
|
30
|
+
export type UpdateTaskInput = z.infer<typeof updateTaskSchema>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
id: code-review-pipeline
|
|
2
|
+
name: Code Review Pipeline
|
|
3
|
+
description: Security scan, quality analysis, and summary report for code changes
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
domain: work
|
|
6
|
+
tags: [code-review, security, quality, owasp]
|
|
7
|
+
pattern: checkpoint
|
|
8
|
+
estimatedDuration: "10-20 min"
|
|
9
|
+
difficulty: intermediate
|
|
10
|
+
author: stagent
|
|
11
|
+
|
|
12
|
+
variables:
|
|
13
|
+
- id: target
|
|
14
|
+
type: text
|
|
15
|
+
label: Review Target
|
|
16
|
+
description: What to review — file path, PR number, or description of changes
|
|
17
|
+
required: true
|
|
18
|
+
placeholder: "e.g., src/lib/auth/ or PR #42"
|
|
19
|
+
- id: focus
|
|
20
|
+
type: select
|
|
21
|
+
label: Review Focus
|
|
22
|
+
description: Primary focus area for the review
|
|
23
|
+
required: true
|
|
24
|
+
default: balanced
|
|
25
|
+
options:
|
|
26
|
+
- { value: security, label: "Security-focused (OWASP, injection, auth)" }
|
|
27
|
+
- { value: quality, label: "Quality-focused (patterns, duplication, naming)" }
|
|
28
|
+
- { value: balanced, label: "Balanced (security + quality)" }
|
|
29
|
+
- id: context
|
|
30
|
+
type: textarea
|
|
31
|
+
label: Additional Context
|
|
32
|
+
description: Any relevant context about the changes being reviewed
|
|
33
|
+
required: false
|
|
34
|
+
placeholder: "e.g., This is a new authentication module..."
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
- name: Security Scan
|
|
38
|
+
profileId: code-reviewer
|
|
39
|
+
promptTemplate: |
|
|
40
|
+
Perform a security-focused code review of: {{target}}
|
|
41
|
+
|
|
42
|
+
Focus: {{focus}}
|
|
43
|
+
{{#if context}}Context: {{context}}{{/if}}
|
|
44
|
+
|
|
45
|
+
Check for OWASP Top 10 vulnerabilities, injection flaws, authentication bypasses,
|
|
46
|
+
and sensitive data exposure. Report each finding with severity, location, and fix.
|
|
47
|
+
requiresApproval: true
|
|
48
|
+
expectedOutput: structured-findings
|
|
49
|
+
|
|
50
|
+
- name: Quality Analysis
|
|
51
|
+
profileId: code-reviewer
|
|
52
|
+
promptTemplate: |
|
|
53
|
+
Perform a code quality analysis of: {{target}}
|
|
54
|
+
|
|
55
|
+
Focus: {{focus}}
|
|
56
|
+
{{#if context}}Context: {{context}}{{/if}}
|
|
57
|
+
|
|
58
|
+
Check for code duplication, naming conventions, error handling patterns,
|
|
59
|
+
test coverage gaps, and performance issues. Report each finding with
|
|
60
|
+
severity (CRITICAL/WARNING/SUGGESTION), location, and recommended fix.
|
|
61
|
+
requiresApproval: false
|
|
62
|
+
expectedOutput: structured-findings
|
|
63
|
+
|
|
64
|
+
- name: Review Summary
|
|
65
|
+
profileId: document-writer
|
|
66
|
+
promptTemplate: |
|
|
67
|
+
Write a concise code review summary for: {{target}}
|
|
68
|
+
|
|
69
|
+
Synthesize the security scan and quality analysis findings from previous steps.
|
|
70
|
+
Structure as: Overview, Critical Issues, Warnings, Suggestions, Verdict (approve/request changes).
|
|
71
|
+
requiresApproval: true
|
|
72
|
+
expectedOutput: markdown-report
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
id: documentation-generation
|
|
2
|
+
name: Documentation Generation
|
|
3
|
+
description: Analyze code, draft documentation, and review for accuracy
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
domain: work
|
|
6
|
+
tags: [documentation, api-docs, technical-writing, readme]
|
|
7
|
+
pattern: sequence
|
|
8
|
+
estimatedDuration: "10-15 min"
|
|
9
|
+
difficulty: beginner
|
|
10
|
+
author: stagent
|
|
11
|
+
|
|
12
|
+
variables:
|
|
13
|
+
- id: target
|
|
14
|
+
type: text
|
|
15
|
+
label: Documentation Target
|
|
16
|
+
description: What to document — module path, API, or component
|
|
17
|
+
required: true
|
|
18
|
+
placeholder: "e.g., src/lib/agents/ or the REST API endpoints"
|
|
19
|
+
- id: docType
|
|
20
|
+
type: select
|
|
21
|
+
label: Documentation Type
|
|
22
|
+
description: What kind of documentation to produce
|
|
23
|
+
required: true
|
|
24
|
+
default: api-docs
|
|
25
|
+
options:
|
|
26
|
+
- { value: api-docs, label: "API Documentation" }
|
|
27
|
+
- { value: readme, label: "README" }
|
|
28
|
+
- { value: adr, label: "Architecture Decision Record" }
|
|
29
|
+
- { value: guide, label: "User Guide" }
|
|
30
|
+
|
|
31
|
+
steps:
|
|
32
|
+
- name: Code Analysis
|
|
33
|
+
profileId: technical-writer
|
|
34
|
+
promptTemplate: |
|
|
35
|
+
Analyze the codebase at: {{target}}
|
|
36
|
+
|
|
37
|
+
Documentation type: {{docType}}
|
|
38
|
+
|
|
39
|
+
Map the public API surface, key abstractions, data flow, and usage patterns.
|
|
40
|
+
Identify what needs to be documented and the logical structure for the docs.
|
|
41
|
+
requiresApproval: false
|
|
42
|
+
expectedOutput: analysis-notes
|
|
43
|
+
|
|
44
|
+
- name: Draft Documentation
|
|
45
|
+
profileId: technical-writer
|
|
46
|
+
promptTemplate: |
|
|
47
|
+
Write {{docType}} documentation for: {{target}}
|
|
48
|
+
|
|
49
|
+
Use the code analysis from the previous step. Follow standard {{docType}} conventions.
|
|
50
|
+
Include code examples, parameter descriptions, return types, and edge cases.
|
|
51
|
+
requiresApproval: false
|
|
52
|
+
expectedOutput: markdown-report
|
|
53
|
+
|
|
54
|
+
- name: Technical Review
|
|
55
|
+
profileId: code-reviewer
|
|
56
|
+
promptTemplate: |
|
|
57
|
+
Review the drafted {{docType}} documentation for: {{target}}
|
|
58
|
+
|
|
59
|
+
Check for: technical accuracy, completeness, code example correctness,
|
|
60
|
+
missing edge cases, and clarity. Suggest specific improvements.
|
|
61
|
+
requiresApproval: true
|
|
62
|
+
expectedOutput: review-feedback
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
id: investment-research
|
|
2
|
+
name: Investment Research
|
|
3
|
+
description: Gather market data, analyze risk, and produce an investment report with disclaimers
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
domain: personal
|
|
6
|
+
tags: [finance, investing, research, risk-assessment]
|
|
7
|
+
pattern: checkpoint
|
|
8
|
+
estimatedDuration: "15-30 min"
|
|
9
|
+
difficulty: advanced
|
|
10
|
+
author: stagent
|
|
11
|
+
|
|
12
|
+
variables:
|
|
13
|
+
- id: asset
|
|
14
|
+
type: text
|
|
15
|
+
label: Asset or Topic
|
|
16
|
+
description: What to research — stock, sector, strategy, or investment question
|
|
17
|
+
required: true
|
|
18
|
+
placeholder: "e.g., NVIDIA stock, index fund vs. active management"
|
|
19
|
+
- id: horizon
|
|
20
|
+
type: select
|
|
21
|
+
label: Investment Horizon
|
|
22
|
+
description: Time frame for the investment
|
|
23
|
+
required: true
|
|
24
|
+
default: medium
|
|
25
|
+
options:
|
|
26
|
+
- { value: short, label: "Short-term (< 1 year)" }
|
|
27
|
+
- { value: medium, label: "Medium-term (1-5 years)" }
|
|
28
|
+
- { value: long, label: "Long-term (5+ years)" }
|
|
29
|
+
- id: riskTolerance
|
|
30
|
+
type: select
|
|
31
|
+
label: Risk Tolerance
|
|
32
|
+
description: Your risk comfort level
|
|
33
|
+
required: true
|
|
34
|
+
default: moderate
|
|
35
|
+
options:
|
|
36
|
+
- { value: conservative, label: "Conservative" }
|
|
37
|
+
- { value: moderate, label: "Moderate" }
|
|
38
|
+
- { value: aggressive, label: "Aggressive" }
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- name: Data Gathering
|
|
42
|
+
profileId: researcher
|
|
43
|
+
promptTemplate: |
|
|
44
|
+
Research the following investment topic: {{asset}}
|
|
45
|
+
|
|
46
|
+
Investment horizon: {{horizon}}
|
|
47
|
+
Risk tolerance: {{riskTolerance}}
|
|
48
|
+
|
|
49
|
+
Gather recent financial data, market trends, analyst opinions, and relevant
|
|
50
|
+
news. Focus on fundamentals, competitive position, and macro factors.
|
|
51
|
+
requiresApproval: false
|
|
52
|
+
expectedOutput: research-data
|
|
53
|
+
|
|
54
|
+
- name: Risk Analysis
|
|
55
|
+
profileId: wealth-manager
|
|
56
|
+
promptTemplate: |
|
|
57
|
+
Analyze the investment risks for: {{asset}}
|
|
58
|
+
|
|
59
|
+
Horizon: {{horizon}}
|
|
60
|
+
Risk tolerance: {{riskTolerance}}
|
|
61
|
+
|
|
62
|
+
Evaluate: market risk, liquidity risk, concentration risk, regulatory risk.
|
|
63
|
+
Provide risk-adjusted return expectations and portfolio fit assessment.
|
|
64
|
+
Include appropriate disclaimers about investment advice.
|
|
65
|
+
requiresApproval: true
|
|
66
|
+
expectedOutput: risk-report
|
|
67
|
+
|
|
68
|
+
- name: Investment Report
|
|
69
|
+
profileId: document-writer
|
|
70
|
+
promptTemplate: |
|
|
71
|
+
Write a comprehensive investment research report on: {{asset}}
|
|
72
|
+
|
|
73
|
+
Horizon: {{horizon}}, Risk tolerance: {{riskTolerance}}
|
|
74
|
+
|
|
75
|
+
Synthesize research and risk analysis from previous steps.
|
|
76
|
+
Structure: Executive Summary, Market Analysis, Risk Assessment,
|
|
77
|
+
Recommendation, Key Risks to Monitor.
|
|
78
|
+
|
|
79
|
+
IMPORTANT: Include standard disclaimers that this is not financial advice.
|
|
80
|
+
requiresApproval: true
|
|
81
|
+
expectedOutput: markdown-report
|