Initialize project and ignore local references
This commit is contained in:
1 parent
a11ac3eaba
commit
2af82b6bb3
132 files changed
+29426
No files matched your search
@@ -0,0 +1,53 @@
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
const extraArgs = process.argv.slice(2);
|
||||
const env = { ...process.env };
|
||||
|
||||
if (env.CSC_IDENTITY_AUTO_DISCOVERY === undefined) {
|
||||
env.CSC_IDENTITY_AUTO_DISCOVERY = "false";
|
||||
}
|
||||
|
||||
const allowedPublishModes = new Set(["always", "never", "onTag", "onTagOrDraft"]);
|
||||
const explicitPublishArg = extraArgs.some((arg) => arg === "--publish" || arg.startsWith("--publish="));
|
||||
const requestedPublishMode = env.AGENTCOMPANY_ELECTRON_PUBLISH?.trim();
|
||||
let publishMode = "never";
|
||||
|
||||
if (requestedPublishMode) {
|
||||
if (!allowedPublishModes.has(requestedPublishMode)) {
|
||||
console.warn(
|
||||
`[build-desktop] Ignoring invalid AGENTCOMPANY_ELECTRON_PUBLISH="${requestedPublishMode}". ` +
|
||||
"Falling back to --publish never.",
|
||||
);
|
||||
} else {
|
||||
publishMode = requestedPublishMode;
|
||||
}
|
||||
}
|
||||
|
||||
const builderArgs = ["exec", "electron-builder", "--config", "electron-builder.yml"];
|
||||
if (!explicitPublishArg) {
|
||||
builderArgs.push("--publish", publishMode);
|
||||
}
|
||||
builderArgs.push(...extraArgs);
|
||||
|
||||
const child = spawn(
|
||||
"pnpm",
|
||||
builderArgs,
|
||||
{
|
||||
stdio: "inherit",
|
||||
env,
|
||||
shell: process.platform === "win32",
|
||||
},
|
||||
);
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
process.exit(code ?? 1);
|
||||
});
|
||||
|
||||
child.on("error", (error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate AgentCompany app icons (PNG, ICO, ICNS, SVG).
|
||||
|
||||
Design v3b: Bold "A" monogram that doubles as an org-chart hierarchy.
|
||||
Two terracotta legs meet at an apex, with three warm crossbars of
|
||||
decreasing brightness (CEO → Managers → ICs). All tones stay warm.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFilter
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ASSETS = ROOT / "assets"
|
||||
ICONSET = ASSETS / "icon.iconset"
|
||||
PNG_PATH = ASSETS / "icon.png"
|
||||
ICO_PATH = ASSETS / "icon.ico"
|
||||
ICNS_PATH = ASSETS / "icon.icns"
|
||||
SVG_PATH = ASSETS / "icon.svg"
|
||||
SIZE = 1024
|
||||
|
||||
# ── Brand palette ──────────────────────────────────────────────────────
|
||||
TERRACOTTA = (217, 119, 69) # #d97745
|
||||
SLATE_TOP = (17, 19, 21) # #111315
|
||||
SLATE_BOT = (27, 31, 35) # #1b1f23
|
||||
|
||||
# Bar colours — all warm, decreasing brightness
|
||||
BAR_CEO = (255, 235, 215) # warm cream — brightest
|
||||
BAR_MGR = (235, 180, 140) # warm peach
|
||||
BAR_IC = (190, 140, 105) # muted terracotta
|
||||
|
||||
|
||||
def rgba(r: int, g: int, b: int, a: int = 255) -> tuple[int, int, int, int]:
|
||||
return (r, g, b, a)
|
||||
|
||||
|
||||
def blend(
|
||||
a: tuple[int, ...], b: tuple[int, ...], t: float,
|
||||
) -> tuple[int, ...]:
|
||||
return tuple(int(a[i] + (b[i] - a[i]) * t) for i in range(len(a)))
|
||||
|
||||
|
||||
def build_icon() -> Image.Image:
|
||||
# ── 1. Gradient background with warm glow ──────────────────────────
|
||||
bg = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
|
||||
px = bg.load()
|
||||
top_c = rgba(*SLATE_TOP)
|
||||
bot_c = rgba(*SLATE_BOT)
|
||||
glow_cx, glow_cy = SIZE * 0.44, SIZE * 0.34
|
||||
glow_r = SIZE * 0.78
|
||||
|
||||
for y in range(SIZE):
|
||||
t = y / (SIZE - 1)
|
||||
base = blend(top_c, bot_c, t)
|
||||
for x in range(SIZE):
|
||||
d = math.hypot(x - glow_cx, y - glow_cy) / glow_r
|
||||
warmth = max(0.0, 1.0 - d) ** 1.8 * 0.13
|
||||
px[x, y] = blend(base, rgba(*TERRACOTTA), warmth)
|
||||
|
||||
# ── 2. Rounded-rect mask + shadow ──────────────────────────────────
|
||||
icon = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
|
||||
mask = Image.new("L", (SIZE, SIZE), 0)
|
||||
inset = 64
|
||||
ImageDraw.Draw(mask).rounded_rectangle(
|
||||
(inset, inset, SIZE - inset, SIZE - inset), radius=224, fill=255,
|
||||
)
|
||||
shadow_alpha = mask.filter(ImageFilter.GaussianBlur(28))
|
||||
shadow_layer = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 48))
|
||||
shadow_layer.putalpha(shadow_alpha)
|
||||
icon.alpha_composite(shadow_layer, (0, 12))
|
||||
icon.alpha_composite(bg)
|
||||
icon.putalpha(mask)
|
||||
|
||||
# ── 3. Draw the "A" mark ───────────────────────────────────────────
|
||||
overlay = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(overlay)
|
||||
|
||||
cx = SIZE // 2
|
||||
apex_y = 200
|
||||
base_y = 800
|
||||
leg_w = 64
|
||||
base_half = 250
|
||||
|
||||
def leg_x(y: int) -> tuple[float, float]:
|
||||
t = (y - apex_y) / (base_y - apex_y)
|
||||
spread = base_half * t
|
||||
return (cx - spread, cx + spread)
|
||||
|
||||
ll_top, _ = leg_x(apex_y)
|
||||
ll_bot, _ = leg_x(base_y)
|
||||
_, lr_top = leg_x(apex_y)
|
||||
_, lr_bot = leg_x(base_y)
|
||||
|
||||
left_leg = [
|
||||
(ll_top - leg_w * 0.35, apex_y),
|
||||
(ll_top + leg_w * 0.35, apex_y),
|
||||
(ll_bot + leg_w, base_y),
|
||||
(ll_bot - leg_w, base_y),
|
||||
]
|
||||
right_leg = [
|
||||
(lr_top - leg_w * 0.35, apex_y),
|
||||
(lr_top + leg_w * 0.35, apex_y),
|
||||
(lr_bot + leg_w, base_y),
|
||||
(lr_bot - leg_w, base_y),
|
||||
]
|
||||
|
||||
draw.polygon(left_leg, fill=rgba(*TERRACOTTA, 240))
|
||||
draw.polygon(right_leg, fill=rgba(*TERRACOTTA, 240))
|
||||
|
||||
# ── 4. Three crossbars — warm tones, hierarchy brightness ──────────
|
||||
bar_h = 42
|
||||
bar_r = 12
|
||||
bar_pad = 14
|
||||
|
||||
tiers = [
|
||||
(440, rgba(*BAR_CEO)),
|
||||
(545, rgba(*BAR_MGR)),
|
||||
(650, rgba(*BAR_IC)),
|
||||
]
|
||||
|
||||
for bar_cy, fill in tiers:
|
||||
left_cx, right_cx = leg_x(bar_cy)
|
||||
bx0 = int(left_cx + bar_pad)
|
||||
bx1 = int(right_cx - bar_pad)
|
||||
draw.rounded_rectangle(
|
||||
(bx0, bar_cy - bar_h // 2, bx1, bar_cy + bar_h // 2),
|
||||
radius=bar_r,
|
||||
fill=fill,
|
||||
)
|
||||
|
||||
# ── 5. Apex beacon ─────────────────────────────────────────────────
|
||||
dot_r = 20
|
||||
dot_cy = apex_y - 2
|
||||
draw.ellipse(
|
||||
(cx - dot_r, dot_cy - dot_r, cx + dot_r, dot_cy + dot_r),
|
||||
fill=rgba(*BAR_CEO),
|
||||
)
|
||||
|
||||
icon.alpha_composite(overlay)
|
||||
return icon
|
||||
|
||||
|
||||
def save_svg() -> None:
|
||||
svg = """\
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="200" x2="824" y1="96" y2="928" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#111315"/>
|
||||
<stop offset="1" stop-color="#1b1f23"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="glow" cx="0" cy="0" r="1"
|
||||
gradientTransform="translate(450 348) rotate(36) scale(800)" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#d97745" stop-opacity=".13"/>
|
||||
<stop offset="1" stop-color="#d97745" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect width="896" height="896" x="64" y="64" rx="224" fill="url(#bg)"/>
|
||||
<rect width="896" height="896" x="64" y="64" rx="224" fill="url(#glow)"/>
|
||||
<polygon points="490,200 534,200 578,800 298,800" fill="#d97745" fill-opacity=".94"/>
|
||||
<polygon points="490,200 534,200 726,800 446,800" fill="#d97745" fill-opacity=".94"/>
|
||||
<rect x="400" y="419" width="224" height="42" rx="12" fill="#ffebd7"/>
|
||||
<rect x="374" y="524" width="276" height="42" rx="12" fill="#ebb48c"/>
|
||||
<rect x="348" y="629" width="328" height="42" rx="12" fill="#be8c69"/>
|
||||
<circle cx="512" cy="198" r="20" fill="#ffebd7"/>
|
||||
</svg>
|
||||
"""
|
||||
SVG_PATH.write_text(svg, encoding="utf-8")
|
||||
|
||||
|
||||
def save_png_and_ico(image: Image.Image) -> None:
|
||||
ASSETS.mkdir(parents=True, exist_ok=True)
|
||||
image.save(PNG_PATH, format="PNG")
|
||||
image.save(
|
||||
ICO_PATH,
|
||||
format="ICO",
|
||||
sizes=[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
|
||||
)
|
||||
|
||||
|
||||
def save_icns(image: Image.Image) -> None:
|
||||
if ICONSET.exists():
|
||||
shutil.rmtree(ICONSET)
|
||||
ICONSET.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for size in (16, 32, 64, 128, 256, 512):
|
||||
image.resize((size, size), Image.Resampling.LANCZOS).save(
|
||||
ICONSET / f"icon_{size}x{size}.png", format="PNG",
|
||||
)
|
||||
image.resize((size * 2, size * 2), Image.Resampling.LANCZOS).save(
|
||||
ICONSET / f"icon_{size}x{size}@2x.png", format="PNG",
|
||||
)
|
||||
|
||||
subprocess.run(
|
||||
["iconutil", "-c", "icns", str(ICONSET), "-o", str(ICNS_PATH)],
|
||||
check=True,
|
||||
)
|
||||
shutil.rmtree(ICONSET)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ASSETS.mkdir(parents=True, exist_ok=True)
|
||||
save_svg()
|
||||
image = build_icon()
|
||||
save_png_and_ico(image)
|
||||
save_icns(image)
|
||||
print(f"Generated: {PNG_PATH}, {ICO_PATH}, {ICNS_PATH}, {SVG_PATH}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Patch the Electron.app bundle name so macOS shows "AgentCompany"
|
||||
# in the dock and menu bar during development.
|
||||
# This runs as a postinstall hook and is safe to re-run.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
APP_NAME="AgentCompany"
|
||||
|
||||
# Find the Electron.app Info.plist (works with pnpm hoisted or nested)
|
||||
PLIST=$(find node_modules -path "*/electron/dist/Electron.app/Contents/Info.plist" -maxdepth 8 2>/dev/null | head -1)
|
||||
|
||||
if [ -z "$PLIST" ]; then
|
||||
echo "[patch-electron-name] Electron.app not found, skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Also find helper plists
|
||||
HELPERS_DIR=$(dirname "$PLIST")/../Frameworks
|
||||
MAIN_PLIST="$PLIST"
|
||||
|
||||
echo "[patch-electron-name] Patching $MAIN_PLIST"
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleName $APP_NAME" "$MAIN_PLIST" 2>/dev/null || true
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $APP_NAME" "$MAIN_PLIST" 2>/dev/null || true
|
||||
|
||||
# Patch helper apps too (they show in Activity Monitor)
|
||||
for HELPER in "$HELPERS_DIR"/Electron\ Helper*.app/Contents/Info.plist; do
|
||||
if [ -f "$HELPER" ]; then
|
||||
HELPER_NAME=$(basename "$(dirname "$(dirname "$HELPER")")" .app | sed "s/Electron Helper/$APP_NAME Helper/")
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleName $HELPER_NAME" "$HELPER" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo "[patch-electron-name] Done — dock and menu bar will show \"$APP_NAME\"."
|
||||
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Seed script: Create a multi-agent Research Company with 8 specialized roles.
|
||||
*
|
||||
* Usage: Run via the AgentCompany API after creating a company and workspace.
|
||||
*
|
||||
* Team Structure:
|
||||
* ProjectManager (CEO — reports to Board)
|
||||
* ├── WebResearcher (IC — primary data gathering)
|
||||
* ├── DataAnalyst (IC — market data synthesis)
|
||||
* ├── ReportArchitect (IC — report writing)
|
||||
* ├── VisualDesigner (IC — presentation design)
|
||||
* ├── FactChecker (IC — source verification)
|
||||
* ├── EnterpriseArchitect (Manager — standards guardian)
|
||||
* │ └── SecurityAuditor (IC — ethics & privacy)
|
||||
* └── (all other ICs report to ProjectManager)
|
||||
*/
|
||||
|
||||
interface AgentDefinition {
|
||||
name: string;
|
||||
role: string;
|
||||
title: string;
|
||||
capabilities: string;
|
||||
reportsTo: string | null; // name of manager, null = CEO
|
||||
connectorId: string;
|
||||
budgetMonthlyUsd: number;
|
||||
}
|
||||
|
||||
const RESEARCH_TEAM: AgentDefinition[] = [
|
||||
{
|
||||
name: "ProjectManager",
|
||||
role: "Research Project Coordinator",
|
||||
title: "CEO — Research Operations",
|
||||
capabilities: [
|
||||
"Review research brief/PRD first.",
|
||||
"Define research objectives, target markets (geographic/demographic), and key questions to answer.",
|
||||
"Create research timeline with milestones (data collection → analysis → report writing).",
|
||||
"Ensure compliance with data privacy regulations (GDPR, CCPA) when collecting public data.",
|
||||
"Define deliverable formats (PDF report, presentation deck, raw data spreadsheet).",
|
||||
"Set authority thresholds (peer-reviewed only, or include industry reports).",
|
||||
"Tools: File system, Documentation viewer, Project management board.",
|
||||
].join(" "),
|
||||
reportsTo: null, // Top-level executive
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 500,
|
||||
},
|
||||
{
|
||||
name: "WebResearcher",
|
||||
role: "Agent Browser Research Specialist",
|
||||
title: "Senior Research Analyst",
|
||||
capabilities: [
|
||||
"PRIMARY DATA GATHERING ROLE.",
|
||||
"Use Agent Browser extensively to gather market data.",
|
||||
"Research competitor websites (feature comparison, pricing pages, positioning statements).",
|
||||
"Search industry reports (Gartner, McKinsey, Statista, IBISWorld).",
|
||||
"Scrape public financial data (earnings reports, SEC 10-K filings, Crunchbase funding data).",
|
||||
"Research social media sentiment (Reddit discussions, LinkedIn professional opinions, Twitter/X trends).",
|
||||
"Find authoritative sources only (.edu, .gov, established publications like WSJ, Reuters).",
|
||||
"Archive all sources with URLs, access dates, and credibility ratings.",
|
||||
"Use advanced search operators (site:, filetype:, intitle:) for precision.",
|
||||
"Never paywall-bypass illegally.",
|
||||
"Tools: Agent Browser, Web scraper (legal/ethical only), Documentation library, Archive.org.",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 300,
|
||||
},
|
||||
{
|
||||
name: "DataAnalyst",
|
||||
role: "Market Data Synthesizer",
|
||||
title: "Senior Data Analyst",
|
||||
capabilities: [
|
||||
"Structure collected data into analytical frameworks (SWOT analysis, Porter's Five Forces, TAM/SAM/SOM market sizing).",
|
||||
"Create comparison matrices for competitor analysis (features, pricing, market share).",
|
||||
"Normalize pricing data across different currencies and regions (PPP adjustment).",
|
||||
"Identify market trends and patterns using statistical methods.",
|
||||
"Verify statistical significance of findings (sample sizes, confidence intervals).",
|
||||
"Create data visualizations (Matplotlib/Seaborn charts, Tableau dashboards) from research findings.",
|
||||
"Flag data gaps and limitations.",
|
||||
"Tools: Spreadsheet (Excel/Google Sheets), Data visualization tools, Python (Pandas, Jupyter), Statistical calculator.",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "codex_local",
|
||||
budgetMonthlyUsd: 250,
|
||||
},
|
||||
{
|
||||
name: "ReportArchitect",
|
||||
role: "Research Report Engineer",
|
||||
title: "Lead Technical Writer",
|
||||
capabilities: [
|
||||
"Write comprehensive research reports with clear structure: Executive Summary, Methodology, Key Findings, Competitive Landscape, Market Trends, Risk Analysis, and Strategic Recommendations.",
|
||||
"Ensure actionable insights (not just data dumping).",
|
||||
"Write for specific target audience (C-suite executives need high-level strategy, Product Managers need feature comparisons).",
|
||||
"Maintain consistent citation style throughout (APA 7th edition recommended).",
|
||||
"Include appendices for raw data and detailed methodology.",
|
||||
"Tools: Document editor (Word/Google Docs), Markdown, Citation manager (Zotero/Mendeley).",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 200,
|
||||
},
|
||||
{
|
||||
name: "VisualDesigner",
|
||||
role: "Research Presentation Designer",
|
||||
title: "Visual Design Specialist",
|
||||
capabilities: [
|
||||
"Design professional layouts for research deliverables.",
|
||||
"Create color-coded competitive landscapes (perceptual maps, magic quadrants).",
|
||||
"Design infographics for key statistics and trends.",
|
||||
"Ensure brand consistency in all materials (client fonts, colors, logos).",
|
||||
"Create presentation templates (PowerPoint/Google Slides) with master slides.",
|
||||
"Optimize layouts for readability and visual hierarchy (information density management).",
|
||||
"Ensure accessibility in charts (colorblind-friendly palettes, alt text).",
|
||||
"Tools: Design software (Figma/Adobe Illustrator), Presentation tools (PowerPoint/Keynote), Image preview.",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "gemini_local",
|
||||
budgetMonthlyUsd: 200,
|
||||
},
|
||||
{
|
||||
name: "FactChecker",
|
||||
role: "Source Verification Specialist",
|
||||
title: "Research Integrity Analyst",
|
||||
capabilities: [
|
||||
"Verify all statistics and claims against original primary sources (not secondary citations).",
|
||||
"Check for outdated information (ensure market data is < 2 years old unless historical trend analysis).",
|
||||
"Identify potential biases in sources (vendor-funded research, self-reported data).",
|
||||
"Cross-reference competitor claims with independent third-party validation.",
|
||||
"Ensure all images/charts have proper attribution and licensing.",
|
||||
"Verify calculation accuracy in market sizing (TAM calculations, CAGR formulas).",
|
||||
"Flag uncertain or questionable data with confidence ratings.",
|
||||
"Tools: Agent Browser (re-verification), Documentation library, Archive.org (historical verification).",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 150,
|
||||
},
|
||||
{
|
||||
name: "EnterpriseArchitect",
|
||||
role: "Research Standards Guardian",
|
||||
title: "Head of Research Integrity",
|
||||
capabilities: [
|
||||
"ENFORCE RESEARCH INTEGRITY STANDARDS:",
|
||||
"NO plagiarism — all content must be original synthesis or properly cited with quotation marks for direct quotes.",
|
||||
"NO unsupported claims — every statistic needs inline citation (Author, Year) or footnote.",
|
||||
"File naming convention: YYYY-MM-DD_Topic_Source_Description.pdf.",
|
||||
"Variable naming in datasets: descriptive snake_case (market_share_percent_2024 not ms24).",
|
||||
"NO circular reporting — Wikipedia cannot cite itself, avoid tertiary sources citing each other.",
|
||||
"Primary sources preferred over secondary (SEC filings > News articles about filings).",
|
||||
"Methodology section must be explicit about data collection methods and limitations.",
|
||||
"NO speculation presented as fact — clearly distinguish between 'Data shows X' and 'Analyst suggests Y might happen'.",
|
||||
"Conflict of interest disclosure mandatory (funded by industry player vs independent).",
|
||||
"Tools: Plagiarism checker (Turnitin/Copyscape), Document editor, Reference manager.",
|
||||
].join(" "),
|
||||
reportsTo: "ProjectManager",
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 200,
|
||||
},
|
||||
{
|
||||
name: "SecurityAuditor",
|
||||
role: "Research Ethics & Privacy Auditor",
|
||||
title: "Privacy & Compliance Officer",
|
||||
capabilities: [
|
||||
"Final audit before delivery:",
|
||||
"Verify no private/personal data (PII) was collected without consent (check datasets for names, emails, phone numbers scraped from social media).",
|
||||
"Ensure no proprietary/trade secret information was accessed inappropriately (no hacked data, no insider leaks).",
|
||||
"Check for defamatory content about competitors (stick to verified facts, no opinion-as-fact).",
|
||||
"Verify licensing of third-party images/data (Creative Commons attribution, Fair Use justification documented).",
|
||||
"Ensure confidential client information is redacted if sample reports contain examples.",
|
||||
"Check that web scraping complied with robots.txt and Terms of Service (rate limiting respected).",
|
||||
"Tools: Privacy scanner (PII detection), Document review, Legal compliance checklist.",
|
||||
].join(" "),
|
||||
reportsTo: "EnterpriseArchitect",
|
||||
connectorId: "claude_local",
|
||||
budgetMonthlyUsd: 150,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Generate curl commands to seed the research team via the AgentCompany API.
|
||||
* Replace $API_URL, $API_KEY, $COMPANY_ID, and $WORKSPACE_ID with real values.
|
||||
*/
|
||||
function generateSetupCommands(): string {
|
||||
const lines: string[] = [
|
||||
"#!/bin/bash",
|
||||
"# Research Company Multi-Agent Team Setup",
|
||||
"# Prerequisites:",
|
||||
"# 1. AgentCompany desktop running with a company and workspace created",
|
||||
"# 2. At least one connector (claude_local) in 'ready' status",
|
||||
"# 3. Set these variables:",
|
||||
"",
|
||||
'API_URL="${AGENT_COMPANY_API_URL:-http://127.0.0.1:3456}"',
|
||||
'API_KEY="${AGENT_COMPANY_API_KEY}"',
|
||||
'COMPANY_ID="${AGENT_COMPANY_COMPANY_ID}"',
|
||||
'WORKSPACE_ID="${AGENT_COMPANY_WORKSPACE_ID}"',
|
||||
"",
|
||||
];
|
||||
|
||||
// Create agents in order (CEO first, then reports)
|
||||
const agentVarMap = new Map<string, string>();
|
||||
|
||||
for (const agent of RESEARCH_TEAM) {
|
||||
const varName = agent.name.toUpperCase() + "_ID";
|
||||
const reportsToVar = agent.reportsTo
|
||||
? agentVarMap.get(agent.reportsTo) ?? "null"
|
||||
: "null";
|
||||
|
||||
agentVarMap.set(agent.name, `$${varName}`);
|
||||
|
||||
lines.push(`# Create ${agent.name} — ${agent.role}`);
|
||||
lines.push(`${varName}=$(curl -s -X POST "$API_URL/api/companies/$COMPANY_ID/agents" \\`);
|
||||
lines.push(` -H "Authorization: Bearer $API_KEY" \\`);
|
||||
lines.push(` -H "Content-Type: application/json" \\`);
|
||||
lines.push(` -d '{`);
|
||||
lines.push(` "name": "${agent.name}",`);
|
||||
lines.push(` "role": "${agent.role}",`);
|
||||
lines.push(` "title": "${agent.title}",`);
|
||||
lines.push(` "connectorId": "${agent.connectorId}",`);
|
||||
lines.push(` "workspaceId": "'$WORKSPACE_ID'",`);
|
||||
lines.push(` "capabilities": ${JSON.stringify(agent.capabilities)},`);
|
||||
lines.push(` "budgetMonthlyUsd": ${agent.budgetMonthlyUsd}${agent.reportsTo ? `,\n "reportsTo": "'${reportsToVar}'"` : ""}`);
|
||||
lines.push(` }' | jq -r '.agentId // .id')`);
|
||||
lines.push(`echo "Created ${agent.name}: $${varName}"`);
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
// Export for use in tests or scripts
|
||||
export { RESEARCH_TEAM, type AgentDefinition };
|
||||
|
||||
// Print setup commands when run directly
|
||||
if (typeof process !== "undefined" && process.argv[1]?.includes("seed-research-team")) {
|
||||
console.log(generateSetupCommands());
|
||||
console.log("\n# Team Structure:");
|
||||
console.log("# ProjectManager (CEO)");
|
||||
console.log("# ├── WebResearcher (IC)");
|
||||
console.log("# ├── DataAnalyst (IC)");
|
||||
console.log("# ├── ReportArchitect (IC)");
|
||||
console.log("# ├── VisualDesigner (IC)");
|
||||
console.log("# ├── FactChecker (IC)");
|
||||
console.log("# └── EnterpriseArchitect (Manager)");
|
||||
console.log("# └── SecurityAuditor (IC)");
|
||||
}
|
||||
Reference in new issue
Block a user