import process from 'node:process'; export const TEMPLATE_AGENT_ID = 'sin-github-issues'; export const TEMPLATE_AGENT_NAME = 'SIN-GitHub-Issues'; export const TEMPLATE_AGENT_DESCRIPTION = 'CEO Elite GitHub Operations Architect — orchestrates Projects V2, Issues, Wikis, Discussions, Gists, Security audits, PR Reviews, and public Showcase Ledger logging.'; export const TEMPLATE_AGENT_VERSION = '2026.03.22'; export const TEMPLATE_AGENT_DEFAULT_HOST = '127.0.0.1'; export const TEMPLATE_AGENT_DEFAULT_PORT = 46031; export const TEMPLATE_AGENT_SKILLS = [ { id: 'sin.github.health', name: 'Health', description: 'Check 2026 Elite GitHub Operations Architect readiness, model, and capabilities.', }, { id: 'sin.github.app.routing.status', name: 'GitHub App Routing Status', description: 'Inspect the configured multi-app GitHub routing table, route paths, and secret readiness without exposing credentials.', }, { id: 'sin.github.webhook.route', name: 'GitHub Webhook Route', description: 'Route GitHub webhook payloads to the correct SIN coder agent using installation.app_id, route path, and signature verification.', }, { id: 'sin.github.issue.comment.as_app', name: 'Issue Comment As App', description: 'Generate the correct GitHub App JWT and installation token, then post an issue or PR comment as the matched bot identity.', }, { id: 'sin.github.project.orchestrate', name: 'Project Orchestrate', description: 'Create and manage GitHub Projects V2 boards, link issues, and assign items.', }, { id: 'sin.github.issue.manage', name: 'Issue Manage', description: 'Create, update, label, assign, milestone-link, or close GitHub issues and Epics.', }, { id: 'sin.github.wiki.sync', name: 'Wiki Sync', description: 'Synchronize repository Wiki pages with project documentation updates.', }, { id: 'sin.github.discussion.start', name: 'Discussion Start', description: 'Start or manage GitHub Discussions for architecture debates and design decisions.', }, { id: 'sin.github.gist.publish', name: 'Gist Publish', description: 'Upload long logs, code snippets, or configs to GitHub Gists and return the URL.', }, { id: 'sin.github.security.audit', name: 'Security Audit', description: 'Audit Dependabot alerts, configure CodeQL, and review active security advisories.', }, { id: 'sin.github.pr.review', name: 'PR Review', description: 'Review Pull Requests for architectural compliance, security, performance, and test coverage. Auto-approve and merge if 100% pass.', }, { id: 'sin.github.issue.pool.enqueue', name: 'Issue Pool Enqueue', description: 'Insert GitHub issue metadata into `sin_issues_pool` for Hermes/Team-Coding dispatch.', }, { id: 'sin.github.ledger.log', name: 'Ledger Log', description: 'Publish an agent activity log or achievement to the public Delqhi/OpenSIN-Ledger showcase repository.', }, ] as const; export function resolveTemplateAgentConfig() { const host = process.env.SIN_GITHUB_ISSUES_HOST?.trim() || (process.env.PORT ? '0.0.0.0' : process.env.HOST?.trim() || TEMPLATE_AGENT_DEFAULT_HOST); const port = parseInteger(process.env.SIN_GITHUB_ISSUES_PORT, parseInteger(process.env.PORT, TEMPLATE_AGENT_DEFAULT_PORT)); const fallbackPublicHost = host === '0.0.0.0' ? '127.0.0.1' : host; const publicBaseUrl = process.env.SIN_GITHUB_ISSUES_PUBLIC_BASE_URL?.trim() || (process.env.SPACE_HOST?.trim() ? `https://${process.env.SPACE_HOST.trim()}` : `http://${fallbackPublicHost}:${port}`); return { host, port, publicBaseUrl: publicBaseUrl.replace(/\/+$/, '') }; } export function buildAgentCard(baseUrl: string) { const normalizedBaseUrl = baseUrl.replace(/\/+$/, ''); const rpcUrl = `${normalizedBaseUrl}/a2a/v1`; return { name: TEMPLATE_AGENT_NAME, description: TEMPLATE_AGENT_DESCRIPTION, version: TEMPLATE_AGENT_VERSION, documentationUrl: normalizedBaseUrl, url: rpcUrl, capabilities: { streaming: false, pushNotifications: false }, defaultInputModes: ['text/plain', 'application/json'], defaultOutputModes: ['text/plain', 'application/json'], skills: [...TEMPLATE_AGENT_SKILLS], supportedInterfaces: [{ url: rpcUrl, protocolBinding: 'JSONRPC', protocolVersion: '1.0' }], }; } function parseInteger(input: string | undefined, fallback: number) { const parsed = Number.parseInt(String(input || '').trim(), 10); return Number.isFinite(parsed) ? parsed : fallback; }