Spaces:
Sleeping
Sleeping
Enable authenticated Room13 worker proof for sin-github-issues
Browse files- .well-known/oauth-client.json +1 -1
- A2A-CARD.md +25 -5
- AGENTS.md +3 -1
- README.md +12 -7
- agent.json +2 -2
- package-lock.json +36 -36
- package.json +2 -0
- scripts/hf_pull_script.py +0 -1
- scripts/smoke-room13-worker.mjs +45 -0
- scripts/smoke-triage-fixtures.mjs +85 -0
- src/a2a-http.ts +5 -0
- src/cli.ts +12 -1
- src/idle-monetization.ts +2 -1
- src/mcp-server.ts +140 -8
- src/metadata.ts +27 -2
- src/queue-state.js +29 -0
- src/queue-state.ts +31 -0
- src/room13-worker.ts +187 -0
- src/runtime.ts +202 -16
- src/self-healing.ts +2 -2
- src/triage.ts +100 -0
.well-known/oauth-client.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"client_id": "https://delqhi-sin-github-issues.hf.space/.well-known/oauth-client.json",
|
| 3 |
-
"client_name": "SIN-GitHub-Issues",
|
| 4 |
"redirect_uris": ["https://delqhi-sin-github-issues.hf.space/oauth/callback"],
|
| 5 |
"grant_types": ["authorization_code"],
|
| 6 |
"response_types": ["code"],
|
|
|
|
| 1 |
{
|
| 2 |
"client_id": "https://delqhi-sin-github-issues.hf.space/.well-known/oauth-client.json",
|
| 3 |
+
"client_name": "AZA-SIN-Coder-•-GitHub-Issues",
|
| 4 |
"redirect_uris": ["https://delqhi-sin-github-issues.hf.space/oauth/callback"],
|
| 5 |
"grant_types": ["authorization_code"],
|
| 6 |
"response_types": ["code"],
|
A2A-CARD.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
**Team:** Coding
|
| 4 |
**Version:** 2026.03.22
|
|
@@ -6,8 +6,8 @@
|
|
| 6 |
|
| 7 |
## Identity & Mandate
|
| 8 |
|
| 9 |
-
> **You are
|
| 10 |
-
> You do NOT just create bug tickets. You orchestrate the **entire repository lifecycle** using the full suite of GitHub's free Enterprise features:
|
| 11 |
>
|
| 12 |
> 1. **Projects (V2)**: You autonomously generate Kanban boards, Epics, Sprints, and assign tasks via the GitHub CLI (`gh project create/link/item-add`).
|
| 13 |
> 2. **Wikis**: You generate, maintain, and sync corporate knowledge base Markdown files to the repo's wiki (`sync-github-wiki.sh`).
|
|
@@ -23,14 +23,34 @@
|
|
| 23 |
## RPC Actions
|
| 24 |
|
| 25 |
- `sin.github.health`: GitHub Operations Architect readiness check.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
- `sin.github.project.orchestrate`: Create and manage GitHub Projects V2 boards.
|
| 27 |
- `sin.github.issue.manage`: Create, update, or close issues (Epics, Sub-tasks).
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
- `sin.github.wiki.sync`: Update the repository Wiki with project documentation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
- `sin.github.discussion.start`: Start an architectural debate in Discussions.
|
| 30 |
- `sin.github.gist.publish`: Upload a large log or code snippet to a Gist.
|
| 31 |
- `sin.github.security.audit`: Audit security alerts and configure Dependabot.
|
| 32 |
- `sin.github.pr.review`: Review and approve/merge Pull Requests.
|
| 33 |
|
| 34 |
## Data & Transport
|
| 35 |
-
|
| 36 |
-
JSON-RPC over HTTP. Strict OpenCode execution via `openai/gpt-5.4` utilizing the `hf_pull_script.py` rotator pool.
|
|
|
|
| 1 |
+
# AZA-SIN-Coder-•-GitHub-Issues (CEO Elite GitHub Operations)
|
| 2 |
|
| 3 |
**Team:** Coding
|
| 4 |
**Version:** 2026.03.22
|
|
|
|
| 6 |
|
| 7 |
## Identity & Mandate
|
| 8 |
|
| 9 |
+
> **You are AZA-SIN-Coder-•-GitHub-Issues, a 2026 CEO-Level GitHub issue triage and delegation architect.**
|
| 10 |
+
> You do NOT just create bug tickets. You triage new issues, comment on them, route them into queues, and orchestrate the **entire repository lifecycle** using the full suite of GitHub's free Enterprise features:
|
| 11 |
>
|
| 12 |
> 1. **Projects (V2)**: You autonomously generate Kanban boards, Epics, Sprints, and assign tasks via the GitHub CLI (`gh project create/link/item-add`).
|
| 13 |
> 2. **Wikis**: You generate, maintain, and sync corporate knowledge base Markdown files to the repo's wiki (`sync-github-wiki.sh`).
|
|
|
|
| 23 |
## RPC Actions
|
| 24 |
|
| 25 |
- `sin.github.health`: GitHub Operations Architect readiness check.
|
| 26 |
+
- `sin.github.worker.register`: Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.
|
| 27 |
+
- `sin.github.worker.status`: Inspect Room-13 worker registration and claim state.
|
| 28 |
+
- `sin.github.worker.claim_next`: Claim the next dispatchable Room-13 task.
|
| 29 |
+
- `sin.github.worker.checkpoint`: Send checkpoint progress for the current Room-13 task.
|
| 30 |
+
- `sin.github.worker.complete`: Mark the currently claimed Room-13 task as completed.
|
| 31 |
- `sin.github.project.orchestrate`: Create and manage GitHub Projects V2 boards.
|
| 32 |
- `sin.github.issue.manage`: Create, update, or close issues (Epics, Sub-tasks).
|
| 33 |
+
- `sin.github.issue.ensure`: Create or update an issue by exact-title match.
|
| 34 |
+
- `sin.github.issue.comment`: Add a GitHub issue comment.
|
| 35 |
+
- `sin.github.issue.close`: Close a GitHub issue with optional comment.
|
| 36 |
+
- `sin.github.issue.triage.enqueue`: Durably enqueue a GitHub issue triage event into the coder dispatch pool.
|
| 37 |
- `sin.github.wiki.sync`: Update the repository Wiki with project documentation.
|
| 38 |
+
|
| 39 |
+
## Ingress Contract
|
| 40 |
+
|
| 41 |
+
- Canonical enqueue payload example: `Docs/operations/phase22-github-issue-triage-payload.example.json`
|
| 42 |
+
- Replay-safe fixture examples:
|
| 43 |
+
- `Docs/operations/phase22-github-issue-opened.fixture.json`
|
| 44 |
+
- `Docs/operations/phase22-github-issue-opened.replay.fixture.json`
|
| 45 |
+
- Primary transport for instant triage: GitHub webhook -> n8n -> `sin.github.issue.triage.enqueue`
|
| 46 |
+
- Idempotency key policy: `delivery_id` first, then fallback `repo#issue_number:event_action`
|
| 47 |
+
- Queue state progression: `received -> queued -> claimed -> dispatched -> accepted -> completed|failed|dead_letter`
|
| 48 |
+
- Runtime queue constants live in `src/queue-state.ts` and are shared between ingress and Hermes dispatch logic.
|
| 49 |
+
- Route contract: ingress computes `assignedTeam`, `assignedAgentHint`, and `capabilityHint` from labels/title/body before Hermes dispatch.
|
| 50 |
+
- Local proof command: `npm run smoke:triage-fixtures`
|
| 51 |
- `sin.github.discussion.start`: Start an architectural debate in Discussions.
|
| 52 |
- `sin.github.gist.publish`: Upload a large log or code snippet to a Gist.
|
| 53 |
- `sin.github.security.audit`: Audit security alerts and configure Dependabot.
|
| 54 |
- `sin.github.pr.review`: Review and approve/merge Pull Requests.
|
| 55 |
|
| 56 |
## Data & Transport
|
|
|
|
|
|
AGENTS.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
-
# SIN-GitHub-Issues
|
| 2 |
|
| 3 |
- Team: Team - Coding
|
| 4 |
- Team Manager: SIN-Coding-CEO
|
| 5 |
- Slug: sin-github-issues
|
|
|
|
|
|
|
| 6 |
- Repo: https://github.com/Delqhi/sin-github-issues
|
| 7 |
- Docs Tab: pending dedicated child-tab
|
| 8 |
|
|
|
|
| 1 |
+
# AZA-SIN-Coder-•-GitHub-Issues
|
| 2 |
|
| 3 |
- Team: Team - Coding
|
| 4 |
- Team Manager: SIN-Coding-CEO
|
| 5 |
- Slug: sin-github-issues
|
| 6 |
+
- Canonical display name: AZA-SIN-Coder-•-GitHub-Issues
|
| 7 |
+
- Machine identity policy: keep slug/package/bin/public route as `sin-github-issues` until an explicit compatibility migration says otherwise
|
| 8 |
- Repo: https://github.com/Delqhi/sin-github-issues
|
| 9 |
- Docs Tab: pending dedicated child-tab
|
| 10 |
|
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title: SIN-GitHub-Issues
|
| 3 |
emoji: "🤖"
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: indigo
|
|
@@ -8,22 +8,23 @@ app_port: 7860
|
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
-
# SIN-GitHub-Issues
|
| 12 |
|
| 13 |
-
`SIN-GitHub-Issues` is
|
| 14 |
|
| 15 |
## Identity
|
| 16 |
|
| 17 |
-
- Slug: `sin-github-issues`
|
| 18 |
- Team: `Team - Coding`
|
| 19 |
- Team Manager: `SIN-Coding-CEO`
|
| 20 |
-
- Purpose: GitHub issue execution agent for confirmed bugs, repo issue lifecycle, branch-based fixes, and verification handoff. Extended with enterprise profile management capabilities.
|
| 21 |
-
- Usage: Use
|
|
|
|
| 22 |
- Primary Model: `opencode/nemotron-3-super-free`
|
| 23 |
|
| 24 |
## Deployment
|
| 25 |
|
| 26 |
-
- Local path: `/Users/jeremy/dev/SIN-Solver/a2a/team-coding/
|
| 27 |
- GitHub repo: `https://github.com/Delqhi/sin-github-issues`
|
| 28 |
- Workforce index: `https://a2a.delqhi.com`
|
| 29 |
- Landing page: `https://delqhi-sin-github-issues.hf.space`
|
|
@@ -76,6 +77,10 @@ sin-github-issues run-action '{"action":"sin.github.issues.issue.evidence.policy
|
|
| 76 |
sin-github-issues run-action '{"action":"sin.github.issues.repo.branch.start","repoPath":"/abs/repo","branchName":"fix/example"}'
|
| 77 |
sin-github-issues run-action '{"action":"sin.github.issues.runners.list","repo":"Delqhi/SIN-Solver"}'
|
| 78 |
sin-github-issues run-action '{"action":"sin.github.issues.workflow.runs.list","repo":"Delqhi/SIN-Solver","branch":"sin-github-issues-bootstrap"}'
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
sin-github-issues run-action '{"action":"sin.github.issues.workflow.local_suite.run","repoPath":"/abs/repo","suite":"docs-and-architecture","confirm":true}'
|
| 80 |
```
|
| 81 |
|
|
|
|
| 1 |
---
|
| 2 |
+
title: AZA-SIN-Coder-•-GitHub-Issues
|
| 3 |
emoji: "🤖"
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: indigo
|
|
|
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
+
# AZA-SIN-Coder-•-GitHub-Issues
|
| 12 |
|
| 13 |
+
`AZA-SIN-Coder-•-GitHub-Issues` is the GitHub issue triage and delegation agent package for the AZA coding workforce.
|
| 14 |
|
| 15 |
## Identity
|
| 16 |
|
| 17 |
+
- Slug: `sin-github-issues` (canonical AZA display name: `AZA-SIN-Coder-•-GitHub-Issues`)
|
| 18 |
- Team: `Team - Coding`
|
| 19 |
- Team Manager: `SIN-Coding-CEO`
|
| 20 |
+
- Purpose: GitHub issue triage, comment, queue, and execution delegation agent for confirmed bugs, repo issue lifecycle, branch-based fixes, and verification handoff. Extended with enterprise profile management capabilities.
|
| 21 |
+
- Usage: Use for instant issue triage and coder delegation as well as confirmed bug workflows to search/create/update GitHub issues, open a repo branch, execute the fix workflow, commit, push, and report verification status back to the orchestrating CLI agent. For profile and achievement operations use the new profile/achievement actions.
|
| 22 |
+
- Durable ingress payload example: `Docs/operations/phase22-github-issue-triage-payload.example.json`
|
| 23 |
- Primary Model: `opencode/nemotron-3-super-free`
|
| 24 |
|
| 25 |
## Deployment
|
| 26 |
|
| 27 |
+
- Local path: `/Users/jeremy/dev/SIN-Solver/a2a/team-coding/AZA-SIN-Coder-•-GitHub-Issues`
|
| 28 |
- GitHub repo: `https://github.com/Delqhi/sin-github-issues`
|
| 29 |
- Workforce index: `https://a2a.delqhi.com`
|
| 30 |
- Landing page: `https://delqhi-sin-github-issues.hf.space`
|
|
|
|
| 77 |
sin-github-issues run-action '{"action":"sin.github.issues.repo.branch.start","repoPath":"/abs/repo","branchName":"fix/example"}'
|
| 78 |
sin-github-issues run-action '{"action":"sin.github.issues.runners.list","repo":"Delqhi/SIN-Solver"}'
|
| 79 |
sin-github-issues run-action '{"action":"sin.github.issues.workflow.runs.list","repo":"Delqhi/SIN-Solver","branch":"sin-github-issues-bootstrap"}'
|
| 80 |
+
sin-github-issues run-action '{"action":"sin.github.worker.register"}'
|
| 81 |
+
sin-github-issues run-action '{"action":"sin.github.worker.status"}'
|
| 82 |
+
sin-github-issues run-action '{"action":"sin.github.worker.claim_next"}'
|
| 83 |
+
cd /Users/jeremy/dev/SIN-Solver/a2a/team-coding/A2A-SIN-GitHub-Issues && npm run smoke:triage-fixtures
|
| 84 |
sin-github-issues run-action '{"action":"sin.github.issues.workflow.local_suite.run","repoPath":"/abs/repo","suite":"docs-and-architecture","confirm":true}'
|
| 85 |
```
|
| 86 |
|
agent.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
{
|
| 2 |
"id": "sin-github-issues",
|
| 3 |
-
"displayName": "
|
| 4 |
"team": "team-coding",
|
| 5 |
-
"description": "Elite 2026 GitHub
|
| 6 |
"version": "2026.03.22",
|
| 7 |
"deployment": {
|
| 8 |
"workforceIndex": "https://a2a.delqhi.com",
|
|
|
|
| 1 |
{
|
| 2 |
"id": "sin-github-issues",
|
| 3 |
+
"displayName": "AZA-SIN-Coder-•-GitHub-Issues",
|
| 4 |
"team": "team-coding",
|
| 5 |
+
"description": "Elite 2026 GitHub issue triage and delegation architect. Manages the entire project lifecycle via GitHub Projects, Issues, comments, queueing, Discussions, Security Alerts (Dependabot/CodeQL), PR Reviews, and Gists. Fully integrated with openai/gpt-5.4 and the A2A Token Pool.",
|
| 6 |
"version": "2026.03.22",
|
| 7 |
"deployment": {
|
| 8 |
"workforceIndex": "https://a2a.delqhi.com",
|
package-lock.json
CHANGED
|
@@ -96,9 +96,9 @@
|
|
| 96 |
}
|
| 97 |
},
|
| 98 |
"node_modules/@supabase/auth-js": {
|
| 99 |
-
"version": "2.
|
| 100 |
-
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.
|
| 101 |
-
"integrity": "sha512-
|
| 102 |
"license": "MIT",
|
| 103 |
"dependencies": {
|
| 104 |
"tslib": "2.8.1"
|
|
@@ -108,9 +108,9 @@
|
|
| 108 |
}
|
| 109 |
},
|
| 110 |
"node_modules/@supabase/functions-js": {
|
| 111 |
-
"version": "2.
|
| 112 |
-
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.
|
| 113 |
-
"integrity": "sha512-
|
| 114 |
"license": "MIT",
|
| 115 |
"dependencies": {
|
| 116 |
"tslib": "2.8.1"
|
|
@@ -119,10 +119,16 @@
|
|
| 119 |
"node": ">=20.0.0"
|
| 120 |
}
|
| 121 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
"node_modules/@supabase/postgrest-js": {
|
| 123 |
-
"version": "2.
|
| 124 |
-
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.
|
| 125 |
-
"integrity": "sha512-
|
| 126 |
"license": "MIT",
|
| 127 |
"dependencies": {
|
| 128 |
"tslib": "2.8.1"
|
|
@@ -132,12 +138,12 @@
|
|
| 132 |
}
|
| 133 |
},
|
| 134 |
"node_modules/@supabase/realtime-js": {
|
| 135 |
-
"version": "2.
|
| 136 |
-
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.
|
| 137 |
-
"integrity": "sha512-
|
| 138 |
"license": "MIT",
|
| 139 |
"dependencies": {
|
| 140 |
-
"@
|
| 141 |
"@types/ws": "^8.18.1",
|
| 142 |
"tslib": "2.8.1",
|
| 143 |
"ws": "^8.18.2"
|
|
@@ -147,9 +153,9 @@
|
|
| 147 |
}
|
| 148 |
},
|
| 149 |
"node_modules/@supabase/storage-js": {
|
| 150 |
-
"version": "2.
|
| 151 |
-
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.
|
| 152 |
-
"integrity": "sha512-
|
| 153 |
"license": "MIT",
|
| 154 |
"dependencies": {
|
| 155 |
"iceberg-js": "^0.8.1",
|
|
@@ -160,16 +166,16 @@
|
|
| 160 |
}
|
| 161 |
},
|
| 162 |
"node_modules/@supabase/supabase-js": {
|
| 163 |
-
"version": "2.
|
| 164 |
-
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.
|
| 165 |
-
"integrity": "sha512-
|
| 166 |
"license": "MIT",
|
| 167 |
"dependencies": {
|
| 168 |
-
"@supabase/auth-js": "2.
|
| 169 |
-
"@supabase/functions-js": "2.
|
| 170 |
-
"@supabase/postgrest-js": "2.
|
| 171 |
-
"@supabase/realtime-js": "2.
|
| 172 |
-
"@supabase/storage-js": "2.
|
| 173 |
},
|
| 174 |
"engines": {
|
| 175 |
"node": ">=20.0.0"
|
|
@@ -191,12 +197,6 @@
|
|
| 191 |
"dev": true,
|
| 192 |
"license": "MIT"
|
| 193 |
},
|
| 194 |
-
"node_modules/@types/phoenix": {
|
| 195 |
-
"version": "1.6.7",
|
| 196 |
-
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz",
|
| 197 |
-
"integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==",
|
| 198 |
-
"license": "MIT"
|
| 199 |
-
},
|
| 200 |
"node_modules/@types/tar": {
|
| 201 |
"version": "6.1.13",
|
| 202 |
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.13.tgz",
|
|
@@ -755,9 +755,9 @@
|
|
| 755 |
}
|
| 756 |
},
|
| 757 |
"node_modules/hono": {
|
| 758 |
-
"version": "4.12.
|
| 759 |
-
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.
|
| 760 |
-
"integrity": "sha512-
|
| 761 |
"license": "MIT",
|
| 762 |
"engines": {
|
| 763 |
"node": ">=16.9.0"
|
|
@@ -1434,9 +1434,9 @@
|
|
| 1434 |
"license": "ISC"
|
| 1435 |
},
|
| 1436 |
"node_modules/ws": {
|
| 1437 |
-
"version": "8.
|
| 1438 |
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.
|
| 1439 |
-
"integrity": "sha512-
|
| 1440 |
"license": "MIT",
|
| 1441 |
"engines": {
|
| 1442 |
"node": ">=10.0.0"
|
|
|
|
| 96 |
}
|
| 97 |
},
|
| 98 |
"node_modules/@supabase/auth-js": {
|
| 99 |
+
"version": "2.100.0",
|
| 100 |
+
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.100.0.tgz",
|
| 101 |
+
"integrity": "sha512-pdT3ye3UVRN1Cg0wom6BmyY+XTtp5DiJaYnPi6j8ht5i8Lq8kfqxJMJz9GI9YDKk3w1nhGOPnh6Qz5qpyYm+1w==",
|
| 102 |
"license": "MIT",
|
| 103 |
"dependencies": {
|
| 104 |
"tslib": "2.8.1"
|
|
|
|
| 108 |
}
|
| 109 |
},
|
| 110 |
"node_modules/@supabase/functions-js": {
|
| 111 |
+
"version": "2.100.0",
|
| 112 |
+
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.100.0.tgz",
|
| 113 |
+
"integrity": "sha512-keLg79RPwP+uiwHuxFPTFgDRxPV46LM4j/swjyR2GKJgWniTVSsgiBHfbIBDcrQwehLepy09b/9QSHUywtKRWQ==",
|
| 114 |
"license": "MIT",
|
| 115 |
"dependencies": {
|
| 116 |
"tslib": "2.8.1"
|
|
|
|
| 119 |
"node": ">=20.0.0"
|
| 120 |
}
|
| 121 |
},
|
| 122 |
+
"node_modules/@supabase/phoenix": {
|
| 123 |
+
"version": "0.4.0",
|
| 124 |
+
"resolved": "https://registry.npmjs.org/@supabase/phoenix/-/phoenix-0.4.0.tgz",
|
| 125 |
+
"integrity": "sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==",
|
| 126 |
+
"license": "MIT"
|
| 127 |
+
},
|
| 128 |
"node_modules/@supabase/postgrest-js": {
|
| 129 |
+
"version": "2.100.0",
|
| 130 |
+
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.100.0.tgz",
|
| 131 |
+
"integrity": "sha512-xYNvNbBJaXOGcrZ44wxwp5830uo1okMHGS8h8dm3u4f0xcZ39yzbryUsubTJW41MG2gbL/6U57cA4Pi6YMZ9pA==",
|
| 132 |
"license": "MIT",
|
| 133 |
"dependencies": {
|
| 134 |
"tslib": "2.8.1"
|
|
|
|
| 138 |
}
|
| 139 |
},
|
| 140 |
"node_modules/@supabase/realtime-js": {
|
| 141 |
+
"version": "2.100.0",
|
| 142 |
+
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.100.0.tgz",
|
| 143 |
+
"integrity": "sha512-2AZs00zzEF0HuCKY8grz5eCYlwEfVi5HONLZFoNR6aDfxQivl8zdQYNjyFoqN2MZiVhQHD7u6XV/xHwM8mCEHw==",
|
| 144 |
"license": "MIT",
|
| 145 |
"dependencies": {
|
| 146 |
+
"@supabase/phoenix": "^0.4.0",
|
| 147 |
"@types/ws": "^8.18.1",
|
| 148 |
"tslib": "2.8.1",
|
| 149 |
"ws": "^8.18.2"
|
|
|
|
| 153 |
}
|
| 154 |
},
|
| 155 |
"node_modules/@supabase/storage-js": {
|
| 156 |
+
"version": "2.100.0",
|
| 157 |
+
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.100.0.tgz",
|
| 158 |
+
"integrity": "sha512-d4EeuK6RNIgYNA2MU9kj8lQrLm5AzZ+WwpWjGkii6SADQNIGTC/uiaTRu02XJ5AmFALQfo8fLl9xuCkO6Xw+iQ==",
|
| 159 |
"license": "MIT",
|
| 160 |
"dependencies": {
|
| 161 |
"iceberg-js": "^0.8.1",
|
|
|
|
| 166 |
}
|
| 167 |
},
|
| 168 |
"node_modules/@supabase/supabase-js": {
|
| 169 |
+
"version": "2.100.0",
|
| 170 |
+
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.100.0.tgz",
|
| 171 |
+
"integrity": "sha512-r0tlcukejJXJ1m/2eG/Ya5eYs4W8AC7oZfShpG3+SIo/eIU9uIt76ZeYI1SoUwUmcmzlAbgch+HDZDR/toVQPQ==",
|
| 172 |
"license": "MIT",
|
| 173 |
"dependencies": {
|
| 174 |
+
"@supabase/auth-js": "2.100.0",
|
| 175 |
+
"@supabase/functions-js": "2.100.0",
|
| 176 |
+
"@supabase/postgrest-js": "2.100.0",
|
| 177 |
+
"@supabase/realtime-js": "2.100.0",
|
| 178 |
+
"@supabase/storage-js": "2.100.0"
|
| 179 |
},
|
| 180 |
"engines": {
|
| 181 |
"node": ">=20.0.0"
|
|
|
|
| 197 |
"dev": true,
|
| 198 |
"license": "MIT"
|
| 199 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
"node_modules/@types/tar": {
|
| 201 |
"version": "6.1.13",
|
| 202 |
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.13.tgz",
|
|
|
|
| 755 |
}
|
| 756 |
},
|
| 757 |
"node_modules/hono": {
|
| 758 |
+
"version": "4.12.9",
|
| 759 |
+
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.9.tgz",
|
| 760 |
+
"integrity": "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==",
|
| 761 |
"license": "MIT",
|
| 762 |
"engines": {
|
| 763 |
"node": ">=16.9.0"
|
|
|
|
| 1434 |
"license": "ISC"
|
| 1435 |
},
|
| 1436 |
"node_modules/ws": {
|
| 1437 |
+
"version": "8.20.0",
|
| 1438 |
+
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
|
| 1439 |
+
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
|
| 1440 |
"license": "MIT",
|
| 1441 |
"engines": {
|
| 1442 |
"node": ">=10.0.0"
|
package.json
CHANGED
|
@@ -10,6 +10,8 @@
|
|
| 10 |
},
|
| 11 |
"scripts": {
|
| 12 |
"build": "rm -rf dist && tsc -p tsconfig.json && node scripts/postbuild.mjs",
|
|
|
|
|
|
|
| 13 |
"typecheck": "tsc --noEmit -p tsconfig.json",
|
| 14 |
"start:a2a": "node dist/src/cli.js serve-a2a",
|
| 15 |
"start:mcp": "node dist/src/cli.js serve-mcp"
|
|
|
|
| 10 |
},
|
| 11 |
"scripts": {
|
| 12 |
"build": "rm -rf dist && tsc -p tsconfig.json && node scripts/postbuild.mjs",
|
| 13 |
+
"smoke:triage-fixtures": "npm run build && node scripts/smoke-triage-fixtures.mjs",
|
| 14 |
+
"smoke:room13-worker": "npm run build && node scripts/smoke-room13-worker.mjs",
|
| 15 |
"typecheck": "tsc --noEmit -p tsconfig.json",
|
| 16 |
"start:a2a": "node dist/src/cli.js serve-a2a",
|
| 17 |
"start:mcp": "node dist/src/cli.js serve-mcp"
|
scripts/hf_pull_script.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
A2A Consumer Rotator (HF VM Pull Script)
|
| 4 |
Pulls a fresh OpenAI token from SIN-Supabase when a rate-limit is hit.
|
| 5 |
Infinite Scaling Architecture.
|
| 6 |
"""
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
|
|
|
| 3 |
Pulls a fresh OpenAI token from SIN-Supabase when a rate-limit is hit.
|
| 4 |
Infinite Scaling Architecture.
|
| 5 |
"""
|
scripts/smoke-room13-worker.mjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env node
|
| 2 |
+
|
| 3 |
+
import { GitHubIssuesRoom13WorkerRuntime, installGitHubIssuesWorkerRuntime } from '../dist/src/room13-worker.js';
|
| 4 |
+
|
| 5 |
+
class FakeWorkerRuntime extends GitHubIssuesRoom13WorkerRuntime {
|
| 6 |
+
constructor() {
|
| 7 |
+
super('sin-github-issues', 'http://room13.test');
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
async start() {
|
| 11 |
+
this.workerId = 'worker-gh';
|
| 12 |
+
this.leaseEpoch = 1;
|
| 13 |
+
this.claimedTaskId = '';
|
| 14 |
+
this.leaseExpiresAt = '2026-03-23T22:30:00Z';
|
| 15 |
+
return this.snapshot();
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
async claimNextTask() {
|
| 19 |
+
this.claimedTaskId = 'task-gh-1';
|
| 20 |
+
return { id: 'task-gh-1', status: 'running' };
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
async checkpoint(step, checkpoint = {}) {
|
| 24 |
+
return { ok: true, step, checkpoint };
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
async completeTask(result = {}) {
|
| 28 |
+
this.claimedTaskId = '';
|
| 29 |
+
return { ok: true, result };
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
const runtime = new FakeWorkerRuntime();
|
| 34 |
+
installGitHubIssuesWorkerRuntime(runtime);
|
| 35 |
+
const registered = await runtime.start();
|
| 36 |
+
const claimed = await runtime.claimNextTask();
|
| 37 |
+
const checkpoint = await runtime.checkpoint('github.issue.sync', { attempt: 1 });
|
| 38 |
+
const completed = await runtime.completeTask({ success: true });
|
| 39 |
+
|
| 40 |
+
if (registered.workerId !== 'worker-gh') throw new Error('worker register smoke failed');
|
| 41 |
+
if (claimed.id !== 'task-gh-1') throw new Error('task claim smoke failed');
|
| 42 |
+
if (checkpoint.step !== 'github.issue.sync') throw new Error('checkpoint smoke failed');
|
| 43 |
+
if (!completed.ok) throw new Error('complete smoke failed');
|
| 44 |
+
|
| 45 |
+
process.stdout.write(JSON.stringify({ ok: true, registered, claimed, checkpoint, completed }, null, 2) + '\n');
|
scripts/smoke-triage-fixtures.mjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env node
|
| 2 |
+
|
| 3 |
+
import { readFile } from 'node:fs/promises';
|
| 4 |
+
import path from 'node:path';
|
| 5 |
+
import process from 'node:process';
|
| 6 |
+
|
| 7 |
+
const packageRoot = path.resolve(process.cwd());
|
| 8 |
+
const repoRoot = path.resolve(packageRoot, '..', '..', '..');
|
| 9 |
+
|
| 10 |
+
const fixtureOnePath = path.join(repoRoot, 'Docs', 'operations', 'phase22-github-issue-opened.fixture.json');
|
| 11 |
+
const fixtureTwoPath = path.join(repoRoot, 'Docs', 'operations', 'phase22-github-issue-opened.replay.fixture.json');
|
| 12 |
+
|
| 13 |
+
const triageModule = await import(path.join(packageRoot, 'dist', 'src', 'triage.js'));
|
| 14 |
+
const queueModule = await import(path.join(packageRoot, 'dist', 'src', 'queue-state.js'));
|
| 15 |
+
|
| 16 |
+
const {
|
| 17 |
+
TriageEnqueueSchema,
|
| 18 |
+
buildDeliveryKey,
|
| 19 |
+
buildIssueKey,
|
| 20 |
+
routeIssueTriage,
|
| 21 |
+
} = triageModule;
|
| 22 |
+
|
| 23 |
+
const { ISSUE_QUEUE_STATE } = queueModule;
|
| 24 |
+
|
| 25 |
+
const rowByDelivery = new Map();
|
| 26 |
+
const rowByIssueKey = new Map();
|
| 27 |
+
|
| 28 |
+
function enqueue(payload) {
|
| 29 |
+
const input = TriageEnqueueSchema.parse(payload);
|
| 30 |
+
const deliveryId = buildDeliveryKey(input);
|
| 31 |
+
const issueKey = buildIssueKey(input.repo, input.issueNumber);
|
| 32 |
+
const route = routeIssueTriage(input.labels || [], input.title, input.body || '');
|
| 33 |
+
|
| 34 |
+
if (rowByDelivery.has(deliveryId)) {
|
| 35 |
+
return {
|
| 36 |
+
created: false,
|
| 37 |
+
deduplicatedBy: 'delivery_id',
|
| 38 |
+
queueState: rowByDelivery.get(deliveryId).queueState,
|
| 39 |
+
deliveryId,
|
| 40 |
+
issueKey,
|
| 41 |
+
route,
|
| 42 |
+
};
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
if (rowByIssueKey.has(issueKey)) {
|
| 46 |
+
const existing = rowByIssueKey.get(issueKey);
|
| 47 |
+
existing.deliveryIds.push(deliveryId);
|
| 48 |
+
rowByDelivery.set(deliveryId, existing);
|
| 49 |
+
return {
|
| 50 |
+
created: false,
|
| 51 |
+
deduplicatedBy: 'issue_key',
|
| 52 |
+
queueState: existing.queueState,
|
| 53 |
+
deliveryId,
|
| 54 |
+
issueKey,
|
| 55 |
+
route,
|
| 56 |
+
};
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
const row = {
|
| 60 |
+
issueKey,
|
| 61 |
+
deliveryIds: [deliveryId],
|
| 62 |
+
queueState: ISSUE_QUEUE_STATE.queued,
|
| 63 |
+
assignedTeam: input.assignedTeam || route.assignedTeam,
|
| 64 |
+
route,
|
| 65 |
+
};
|
| 66 |
+
rowByDelivery.set(deliveryId, row);
|
| 67 |
+
rowByIssueKey.set(issueKey, row);
|
| 68 |
+
return {
|
| 69 |
+
created: true,
|
| 70 |
+
deduplicatedBy: null,
|
| 71 |
+
queueState: row.queueState,
|
| 72 |
+
deliveryId,
|
| 73 |
+
issueKey,
|
| 74 |
+
route,
|
| 75 |
+
};
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
const first = enqueue(JSON.parse(await readFile(fixtureOnePath, 'utf8')));
|
| 79 |
+
const replay = enqueue(JSON.parse(await readFile(fixtureTwoPath, 'utf8')));
|
| 80 |
+
|
| 81 |
+
if (!first.created) throw new Error('expected first fixture to create queue row');
|
| 82 |
+
if (replay.created || replay.deduplicatedBy !== 'delivery_id') throw new Error('expected replay fixture to deduplicate by delivery_id');
|
| 83 |
+
if (rowByIssueKey.size !== 1) throw new Error(`expected exactly one queue row, got ${rowByIssueKey.size}`);
|
| 84 |
+
|
| 85 |
+
process.stdout.write(JSON.stringify({ ok: true, createdRows: rowByIssueKey.size, first, replay, finalRow: [...rowByIssueKey.values()][0] }, null, 2) + '\n');
|
src/a2a-http.ts
CHANGED
|
@@ -31,6 +31,11 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse,
|
|
| 31 |
}
|
| 32 |
if (request.method === 'POST' && request.url === '/a2a/v1') {
|
| 33 |
const rpc = ((await readJson(request)) || {}) as RpcRequest;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
if (rpc.method === 'agent/getCard') return sendJson(response, 200, { jsonrpc: '2.0', id: rpc.id ?? null, result: buildAgentCard(baseUrl) });
|
| 35 |
if (rpc.method === 'message/send') {
|
| 36 |
const action = parseAction((rpc.params?.message as { parts?: Array<{ text?: string }> } | undefined)?.parts?.map((part) => part.text || '').join(' ').trim() || '');
|
|
|
|
| 31 |
}
|
| 32 |
if (request.method === 'POST' && request.url === '/a2a/v1') {
|
| 33 |
const rpc = ((await readJson(request)) || {}) as RpcRequest;
|
| 34 |
+
if (rpc && typeof rpc === 'object' && 'action' in rpc && typeof (rpc as { action?: unknown }).action === 'string') {
|
| 35 |
+
const action = rpc as unknown as GitHubAgentAction;
|
| 36 |
+
const result = await executeGitHubAgentAction(action);
|
| 37 |
+
return sendJson(response, 200, { ok: true, agent: TEMPLATE_AGENT_ID, action: action.action, result });
|
| 38 |
+
}
|
| 39 |
if (rpc.method === 'agent/getCard') return sendJson(response, 200, { jsonrpc: '2.0', id: rpc.id ?? null, result: buildAgentCard(baseUrl) });
|
| 40 |
if (rpc.method === 'message/send') {
|
| 41 |
const action = parseAction((rpc.params?.message as { parts?: Array<{ text?: string }> } | undefined)?.parts?.map((part) => part.text || '').join(' ').trim() || '');
|
src/cli.ts
CHANGED
|
@@ -5,11 +5,22 @@ import { resolve } from 'node:path';
|
|
| 5 |
import { createTemplateAgentHttpServer } from './a2a-http.js';
|
| 6 |
import { runMcpServer } from './mcp-server.js';
|
| 7 |
import { executeGitHubAgentAction } from './runtime.js';
|
|
|
|
| 8 |
|
| 9 |
const cmd = process.argv[2];
|
| 10 |
|
| 11 |
if (cmd === 'serve-a2a') {
|
| 12 |
-
createTemplateAgentHttpServer().start().
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
console.error(err);
|
| 14 |
process.exit(1);
|
| 15 |
});
|
|
|
|
| 5 |
import { createTemplateAgentHttpServer } from './a2a-http.js';
|
| 6 |
import { runMcpServer } from './mcp-server.js';
|
| 7 |
import { executeGitHubAgentAction } from './runtime.js';
|
| 8 |
+
import { GitHubIssuesRoom13WorkerRuntime, installGitHubIssuesWorkerRuntime } from './room13-worker.js';
|
| 9 |
|
| 10 |
const cmd = process.argv[2];
|
| 11 |
|
| 12 |
if (cmd === 'serve-a2a') {
|
| 13 |
+
createTemplateAgentHttpServer().start().then(async () => {
|
| 14 |
+
const room13Worker = new GitHubIssuesRoom13WorkerRuntime('sin-github-issues');
|
| 15 |
+
installGitHubIssuesWorkerRuntime(room13Worker);
|
| 16 |
+
await room13Worker.start().catch(() => undefined);
|
| 17 |
+
const stop = async () => {
|
| 18 |
+
await room13Worker.stop().catch(() => undefined);
|
| 19 |
+
process.exit(0);
|
| 20 |
+
};
|
| 21 |
+
process.once('SIGINT', () => void stop());
|
| 22 |
+
process.once('SIGTERM', () => void stop());
|
| 23 |
+
}).catch(err => {
|
| 24 |
console.error(err);
|
| 25 |
process.exit(1);
|
| 26 |
});
|
src/idle-monetization.ts
CHANGED
|
@@ -6,11 +6,12 @@
|
|
| 6 |
|
| 7 |
export function startAutonomousIdleLoop() {
|
| 8 |
console.log('💸 Autonomous Monetization & Hacking loop enabled (Mega Krass Mode).');
|
|
|
|
| 9 |
|
| 10 |
// The loop checks every 5 minutes if the agent is idle.
|
| 11 |
setInterval(async () => {
|
| 12 |
// Skip if currently busy with a user or fleet task
|
| 13 |
-
if (
|
| 14 |
return;
|
| 15 |
}
|
| 16 |
|
|
|
|
| 6 |
|
| 7 |
export function startAutonomousIdleLoop() {
|
| 8 |
console.log('💸 Autonomous Monetization & Hacking loop enabled (Mega Krass Mode).');
|
| 9 |
+
const runtimeState = globalThis as typeof globalThis & { isAgentBusy?: boolean };
|
| 10 |
|
| 11 |
// The loop checks every 5 minutes if the agent is idle.
|
| 12 |
setInterval(async () => {
|
| 13 |
// Skip if currently busy with a user or fleet task
|
| 14 |
+
if (runtimeState.isAgentBusy) {
|
| 15 |
return;
|
| 16 |
}
|
| 17 |
|
src/mcp-server.ts
CHANGED
|
@@ -16,6 +16,43 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
| 16 |
description: 'Check 2026 Elite GitHub Operations Architect readiness.',
|
| 17 |
inputSchema: { type: 'object', properties: {} },
|
| 18 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
{
|
| 20 |
name: 'sin_github_project_orchestrate',
|
| 21 |
description: 'Create and manage GitHub Projects V2 boards.',
|
|
@@ -40,6 +77,64 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
| 40 |
required: ['prompt'],
|
| 41 |
},
|
| 42 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
{
|
| 44 |
name: 'sin_github_wiki_sync',
|
| 45 |
description: 'Update the repository Wiki with project documentation.',
|
|
@@ -122,16 +217,53 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
| 122 |
let action: GitHubAgentAction;
|
| 123 |
const args = request.params.arguments as any;
|
| 124 |
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
case 'sin_github_issue_manage':
|
| 133 |
action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber };
|
| 134 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
case 'sin_github_wiki_sync':
|
| 136 |
action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir };
|
| 137 |
break;
|
|
@@ -169,5 +301,5 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
| 169 |
export async function runMcpServer() {
|
| 170 |
const transport = new StdioServerTransport();
|
| 171 |
await server.connect(transport);
|
| 172 |
-
console.error('
|
| 173 |
}
|
|
|
|
| 16 |
description: 'Check 2026 Elite GitHub Operations Architect readiness.',
|
| 17 |
inputSchema: { type: 'object', properties: {} },
|
| 18 |
},
|
| 19 |
+
{
|
| 20 |
+
name: 'sin_github_worker_register',
|
| 21 |
+
description: 'Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.',
|
| 22 |
+
inputSchema: { type: 'object', properties: {} },
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
name: 'sin_github_worker_status',
|
| 26 |
+
description: 'Inspect Room-13 worker registration and claim state for GitHub-Issues.',
|
| 27 |
+
inputSchema: { type: 'object', properties: {} },
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
name: 'sin_github_worker_claim_next',
|
| 31 |
+
description: 'Claim the next Room-13 task for GitHub-Issues.',
|
| 32 |
+
inputSchema: { type: 'object', properties: {} },
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
name: 'sin_github_worker_checkpoint',
|
| 36 |
+
description: 'Send a checkpoint to Room-13 for GitHub-Issues.',
|
| 37 |
+
inputSchema: {
|
| 38 |
+
type: 'object',
|
| 39 |
+
properties: {
|
| 40 |
+
step: { type: 'string' },
|
| 41 |
+
checkpoint: { type: 'object' }
|
| 42 |
+
},
|
| 43 |
+
required: ['step']
|
| 44 |
+
}
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
name: 'sin_github_worker_complete',
|
| 48 |
+
description: 'Complete the currently claimed Room-13 task for GitHub-Issues.',
|
| 49 |
+
inputSchema: {
|
| 50 |
+
type: 'object',
|
| 51 |
+
properties: {
|
| 52 |
+
result: { type: 'object' }
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
},
|
| 56 |
{
|
| 57 |
name: 'sin_github_project_orchestrate',
|
| 58 |
description: 'Create and manage GitHub Projects V2 boards.',
|
|
|
|
| 77 |
required: ['prompt'],
|
| 78 |
},
|
| 79 |
},
|
| 80 |
+
{
|
| 81 |
+
name: 'sin_github_issue_ensure',
|
| 82 |
+
description: 'Create or update an issue by exact title match.',
|
| 83 |
+
inputSchema: {
|
| 84 |
+
type: 'object',
|
| 85 |
+
properties: {
|
| 86 |
+
repo: { type: 'string' },
|
| 87 |
+
title: { type: 'string' },
|
| 88 |
+
body: { type: 'string' },
|
| 89 |
+
labels: { type: 'array', items: { type: 'string' } }
|
| 90 |
+
},
|
| 91 |
+
required: ['repo', 'title', 'body']
|
| 92 |
+
}
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
name: 'sin_github_issue_comment',
|
| 96 |
+
description: 'Comment on a GitHub issue.',
|
| 97 |
+
inputSchema: {
|
| 98 |
+
type: 'object',
|
| 99 |
+
properties: {
|
| 100 |
+
repo: { type: 'string' },
|
| 101 |
+
issueNumber: { type: 'number' },
|
| 102 |
+
body: { type: 'string' }
|
| 103 |
+
},
|
| 104 |
+
required: ['repo', 'issueNumber', 'body']
|
| 105 |
+
}
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
name: 'sin_github_issue_close',
|
| 109 |
+
description: 'Close a GitHub issue with optional comment.',
|
| 110 |
+
inputSchema: {
|
| 111 |
+
type: 'object',
|
| 112 |
+
properties: {
|
| 113 |
+
repo: { type: 'string' },
|
| 114 |
+
issueNumber: { type: 'number' },
|
| 115 |
+
comment: { type: 'string' }
|
| 116 |
+
},
|
| 117 |
+
required: ['repo', 'issueNumber']
|
| 118 |
+
}
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
name: 'sin_github_issue_triage_enqueue',
|
| 122 |
+
description: 'Durably enqueue a GitHub issue triage event into the coder dispatch pool.',
|
| 123 |
+
inputSchema: {
|
| 124 |
+
type: 'object',
|
| 125 |
+
properties: {
|
| 126 |
+
repo: { type: 'string' },
|
| 127 |
+
issueNumber: { type: 'number' },
|
| 128 |
+
title: { type: 'string' },
|
| 129 |
+
body: { type: 'string' },
|
| 130 |
+
labels: { type: 'array', items: { type: 'string' } },
|
| 131 |
+
assignedTeam: { type: 'string' },
|
| 132 |
+
deliveryId: { type: 'string' },
|
| 133 |
+
eventAction: { type: 'string' }
|
| 134 |
+
},
|
| 135 |
+
required: ['repo', 'issueNumber', 'title']
|
| 136 |
+
}
|
| 137 |
+
},
|
| 138 |
{
|
| 139 |
name: 'sin_github_wiki_sync',
|
| 140 |
description: 'Update the repository Wiki with project documentation.',
|
|
|
|
| 217 |
let action: GitHubAgentAction;
|
| 218 |
const args = request.params.arguments as any;
|
| 219 |
|
| 220 |
+
switch (request.params.name) {
|
| 221 |
+
case 'sin_github_health':
|
| 222 |
+
action = { action: 'sin.github.health' };
|
| 223 |
+
break;
|
| 224 |
+
case 'sin_github_worker_register':
|
| 225 |
+
action = { action: 'sin.github.worker.register' };
|
| 226 |
+
break;
|
| 227 |
+
case 'sin_github_worker_status':
|
| 228 |
+
action = { action: 'sin.github.worker.status' };
|
| 229 |
+
break;
|
| 230 |
+
case 'sin_github_worker_claim_next':
|
| 231 |
+
action = { action: 'sin.github.worker.claim_next' };
|
| 232 |
+
break;
|
| 233 |
+
case 'sin_github_worker_checkpoint':
|
| 234 |
+
action = { action: 'sin.github.worker.checkpoint', step: args.step, checkpoint: args.checkpoint };
|
| 235 |
+
break;
|
| 236 |
+
case 'sin_github_worker_complete':
|
| 237 |
+
action = { action: 'sin.github.worker.complete', result: args.result };
|
| 238 |
+
break;
|
| 239 |
+
case 'sin_github_project_orchestrate':
|
| 240 |
+
action = { action: 'sin.github.project.orchestrate', prompt: args.prompt, contextDir: args.contextDir };
|
| 241 |
+
break;
|
| 242 |
case 'sin_github_issue_manage':
|
| 243 |
action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber };
|
| 244 |
break;
|
| 245 |
+
case 'sin_github_issue_ensure':
|
| 246 |
+
action = { action: 'sin.github.issue.ensure', repo: args.repo, title: args.title, body: args.body, labels: args.labels };
|
| 247 |
+
break;
|
| 248 |
+
case 'sin_github_issue_comment':
|
| 249 |
+
action = { action: 'sin.github.issue.comment', repo: args.repo, issueNumber: args.issueNumber, body: args.body };
|
| 250 |
+
break;
|
| 251 |
+
case 'sin_github_issue_close':
|
| 252 |
+
action = { action: 'sin.github.issue.close', repo: args.repo, issueNumber: args.issueNumber, comment: args.comment };
|
| 253 |
+
break;
|
| 254 |
+
case 'sin_github_issue_triage_enqueue':
|
| 255 |
+
action = {
|
| 256 |
+
action: 'sin.github.issue.triage.enqueue',
|
| 257 |
+
repo: args.repo,
|
| 258 |
+
issueNumber: args.issueNumber,
|
| 259 |
+
title: args.title,
|
| 260 |
+
body: args.body,
|
| 261 |
+
labels: args.labels,
|
| 262 |
+
assignedTeam: args.assignedTeam,
|
| 263 |
+
deliveryId: args.deliveryId,
|
| 264 |
+
eventAction: args.eventAction
|
| 265 |
+
};
|
| 266 |
+
break;
|
| 267 |
case 'sin_github_wiki_sync':
|
| 268 |
action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir };
|
| 269 |
break;
|
|
|
|
| 301 |
export async function runMcpServer() {
|
| 302 |
const transport = new StdioServerTransport();
|
| 303 |
await server.connect(transport);
|
| 304 |
+
console.error('AZA-SIN-Coder-•-GitHub-Issues MCP Server running on stdio');
|
| 305 |
}
|
src/metadata.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
import process from 'node:process';
|
| 2 |
|
| 3 |
export const TEMPLATE_AGENT_ID = 'sin-github-issues';
|
| 4 |
-
export const TEMPLATE_AGENT_NAME = 'SIN-GitHub-Issues';
|
| 5 |
-
export const TEMPLATE_AGENT_DESCRIPTION = 'CEO Elite GitHub
|
| 6 |
export const TEMPLATE_AGENT_VERSION = '2026.03.22';
|
| 7 |
export const TEMPLATE_AGENT_DEFAULT_HOST = '127.0.0.1';
|
| 8 |
export const TEMPLATE_AGENT_DEFAULT_PORT = 46031;
|
|
@@ -13,6 +13,31 @@ export const TEMPLATE_AGENT_SKILLS = [
|
|
| 13 |
name: 'Health',
|
| 14 |
description: 'Check 2026 Elite GitHub Operations Architect readiness, model, and capabilities.',
|
| 15 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
{
|
| 17 |
id: 'sin.github.project.orchestrate',
|
| 18 |
name: 'Project Orchestrate',
|
|
|
|
| 1 |
import process from 'node:process';
|
| 2 |
|
| 3 |
export const TEMPLATE_AGENT_ID = 'sin-github-issues';
|
| 4 |
+
export const TEMPLATE_AGENT_NAME = 'AZA-SIN-Coder-•-GitHub-Issues';
|
| 5 |
+
export const TEMPLATE_AGENT_DESCRIPTION = 'CEO Elite GitHub issue triage and delegation architect for the AZA coding fleet — orchestrates issue lifecycle, comments, queueing, Projects V2, Discussions, Gists, Security audits, PR reviews, and public Showcase Ledger logging.';
|
| 6 |
export const TEMPLATE_AGENT_VERSION = '2026.03.22';
|
| 7 |
export const TEMPLATE_AGENT_DEFAULT_HOST = '127.0.0.1';
|
| 8 |
export const TEMPLATE_AGENT_DEFAULT_PORT = 46031;
|
|
|
|
| 13 |
name: 'Health',
|
| 14 |
description: 'Check 2026 Elite GitHub Operations Architect readiness, model, and capabilities.',
|
| 15 |
},
|
| 16 |
+
{
|
| 17 |
+
id: 'sin.github.worker.register',
|
| 18 |
+
name: 'Worker Register',
|
| 19 |
+
description: 'Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.',
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
id: 'sin.github.worker.status',
|
| 23 |
+
name: 'Worker Status',
|
| 24 |
+
description: 'Inspect GitHub-Issues worker registration and claim state against Room-13.',
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
id: 'sin.github.worker.claim_next',
|
| 28 |
+
name: 'Worker Claim Next',
|
| 29 |
+
description: 'Claim the next dispatchable Room-13 task for GitHub-Issues.',
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
id: 'sin.github.worker.checkpoint',
|
| 33 |
+
name: 'Worker Checkpoint',
|
| 34 |
+
description: 'Send checkpoint progress for the current Room-13 task.',
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
id: 'sin.github.worker.complete',
|
| 38 |
+
name: 'Worker Complete',
|
| 39 |
+
description: 'Mark the currently claimed Room-13 task as completed.',
|
| 40 |
+
},
|
| 41 |
{
|
| 42 |
id: 'sin.github.project.orchestrate',
|
| 43 |
name: 'Project Orchestrate',
|
src/queue-state.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const ISSUE_QUEUE_STATE = {
|
| 2 |
+
received: 'received',
|
| 3 |
+
queued: 'queued',
|
| 4 |
+
claimed: 'claimed',
|
| 5 |
+
dispatched: 'dispatched',
|
| 6 |
+
accepted: 'accepted',
|
| 7 |
+
completed: 'completed',
|
| 8 |
+
failed: 'failed',
|
| 9 |
+
dead_letter: 'dead_letter',
|
| 10 |
+
};
|
| 11 |
+
|
| 12 |
+
export function isActiveQueueState(value) {
|
| 13 |
+
return ['received', 'queued', 'claimed', 'dispatched', 'accepted'].includes(String(value || ''));
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
export function queueStateForStatus(value) {
|
| 17 |
+
switch (String(value || '').toLowerCase()) {
|
| 18 |
+
case 'pending':
|
| 19 |
+
return ISSUE_QUEUE_STATE.queued;
|
| 20 |
+
case 'in_progress':
|
| 21 |
+
return ISSUE_QUEUE_STATE.claimed;
|
| 22 |
+
case 'completed':
|
| 23 |
+
return ISSUE_QUEUE_STATE.completed;
|
| 24 |
+
case 'failed':
|
| 25 |
+
return ISSUE_QUEUE_STATE.failed;
|
| 26 |
+
default:
|
| 27 |
+
return ISSUE_QUEUE_STATE.received;
|
| 28 |
+
}
|
| 29 |
+
}
|
src/queue-state.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const ISSUE_QUEUE_STATE = {
|
| 2 |
+
received: 'received',
|
| 3 |
+
queued: 'queued',
|
| 4 |
+
claimed: 'claimed',
|
| 5 |
+
dispatched: 'dispatched',
|
| 6 |
+
accepted: 'accepted',
|
| 7 |
+
completed: 'completed',
|
| 8 |
+
failed: 'failed',
|
| 9 |
+
dead_letter: 'dead_letter',
|
| 10 |
+
} as const;
|
| 11 |
+
|
| 12 |
+
export type IssueQueueState = keyof typeof ISSUE_QUEUE_STATE;
|
| 13 |
+
|
| 14 |
+
export function isActiveQueueState(value: string | null | undefined): boolean {
|
| 15 |
+
return ['received', 'queued', 'claimed', 'dispatched', 'accepted'].includes(String(value || ''));
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
export function queueStateForStatus(status: string | null | undefined): IssueQueueState {
|
| 19 |
+
switch (String(status || '').toLowerCase()) {
|
| 20 |
+
case 'pending':
|
| 21 |
+
return 'queued';
|
| 22 |
+
case 'in_progress':
|
| 23 |
+
return 'claimed';
|
| 24 |
+
case 'completed':
|
| 25 |
+
return 'completed';
|
| 26 |
+
case 'failed':
|
| 27 |
+
return 'failed';
|
| 28 |
+
default:
|
| 29 |
+
return 'received';
|
| 30 |
+
}
|
| 31 |
+
}
|
src/room13-worker.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os from 'node:os';
|
| 2 |
+
import process from 'node:process';
|
| 3 |
+
|
| 4 |
+
type Room13WorkerRegisterResponse = {
|
| 5 |
+
id?: string;
|
| 6 |
+
lease_epoch?: number;
|
| 7 |
+
};
|
| 8 |
+
|
| 9 |
+
type Room13WorkerClaimResponse = {
|
| 10 |
+
claimed_task_id?: string | null;
|
| 11 |
+
lease_epoch?: number;
|
| 12 |
+
lease_expires_at?: string | null;
|
| 13 |
+
run_id?: string;
|
| 14 |
+
};
|
| 15 |
+
|
| 16 |
+
type Room13Task = {
|
| 17 |
+
id: string;
|
| 18 |
+
status: string;
|
| 19 |
+
assigned_worker?: string | null;
|
| 20 |
+
run_id?: string | null;
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
+
export type GitHubIssuesWorkerSnapshot = {
|
| 24 |
+
enabled: boolean;
|
| 25 |
+
workerName: string;
|
| 26 |
+
workerId: string;
|
| 27 |
+
runId: string;
|
| 28 |
+
claimedTaskId: string;
|
| 29 |
+
leaseEpoch: number;
|
| 30 |
+
leaseExpiresAt?: string;
|
| 31 |
+
baseUrl: string;
|
| 32 |
+
};
|
| 33 |
+
|
| 34 |
+
let currentRuntime: GitHubIssuesRoom13WorkerRuntime | null = null;
|
| 35 |
+
|
| 36 |
+
export function getCurrentGitHubIssuesWorkerRuntime() {
|
| 37 |
+
return currentRuntime;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
export class GitHubIssuesRoom13WorkerRuntime {
|
| 41 |
+
protected workerId = '';
|
| 42 |
+
protected leaseEpoch = 0;
|
| 43 |
+
protected claimedTaskId = '';
|
| 44 |
+
protected leaseExpiresAt?: string;
|
| 45 |
+
protected readonly workerName: string;
|
| 46 |
+
protected readonly baseUrl: string;
|
| 47 |
+
protected readonly bearerToken: string;
|
| 48 |
+
protected readonly runId: string;
|
| 49 |
+
protected heartbeatTimer?: NodeJS.Timeout;
|
| 50 |
+
|
| 51 |
+
constructor(workerName = 'sin-github-issues', baseUrl = process.env.ROOM13_COORDINATOR_URL || '') {
|
| 52 |
+
this.workerName = workerName;
|
| 53 |
+
this.baseUrl = baseUrl.replace(/\/$/, '');
|
| 54 |
+
this.bearerToken = String(process.env.ROOM13_BEARER_TOKEN || '').trim();
|
| 55 |
+
this.runId = `${workerName}:${process.pid}:${Date.now()}`;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
get enabled() {
|
| 59 |
+
return Boolean(this.baseUrl);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
snapshot(): GitHubIssuesWorkerSnapshot {
|
| 63 |
+
return {
|
| 64 |
+
enabled: this.enabled,
|
| 65 |
+
workerName: this.workerName,
|
| 66 |
+
workerId: this.workerId,
|
| 67 |
+
runId: this.runId,
|
| 68 |
+
claimedTaskId: this.claimedTaskId,
|
| 69 |
+
leaseEpoch: this.leaseEpoch,
|
| 70 |
+
leaseExpiresAt: this.leaseExpiresAt,
|
| 71 |
+
baseUrl: this.baseUrl,
|
| 72 |
+
};
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
async start() {
|
| 76 |
+
if (!this.enabled) return this.snapshot();
|
| 77 |
+
const registered = await this.request<Room13WorkerRegisterResponse>('POST', '/api/workers', {
|
| 78 |
+
name: `${this.workerName}:${process.env.SPACE_HOST || 'local'}`,
|
| 79 |
+
type: 'general',
|
| 80 |
+
capabilities: ['platform:github', 'worker_runtime', 'lease_heartbeat', 'issue_lifecycle'],
|
| 81 |
+
metadata: { runtime: 'node', hostname: os.hostname() },
|
| 82 |
+
worker_identity: this.workerName,
|
| 83 |
+
persona_id: this.workerName,
|
| 84 |
+
platform: 'github-issues',
|
| 85 |
+
current_run_id: this.runId,
|
| 86 |
+
lease_ttl_sec: 120,
|
| 87 |
+
approval_state: 'idle',
|
| 88 |
+
});
|
| 89 |
+
this.workerId = String(registered?.id || '').trim();
|
| 90 |
+
this.leaseEpoch = Number(registered?.lease_epoch || 0);
|
| 91 |
+
if (this.workerId) {
|
| 92 |
+
const claim = await this.request<Room13WorkerClaimResponse>('POST', `/api/workers/${this.workerId}/claim`, {
|
| 93 |
+
run_id: this.runId,
|
| 94 |
+
ttl_sec: 120,
|
| 95 |
+
});
|
| 96 |
+
this.claimedTaskId = String(claim?.claimed_task_id || '').trim();
|
| 97 |
+
this.leaseEpoch = Number(claim?.lease_epoch || this.leaseEpoch || 0);
|
| 98 |
+
this.leaseExpiresAt = claim?.lease_expires_at || undefined;
|
| 99 |
+
this.startHeartbeatLoop();
|
| 100 |
+
}
|
| 101 |
+
return this.snapshot();
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
async stop() {
|
| 105 |
+
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
| 106 |
+
if (!this.enabled || !this.workerId) return;
|
| 107 |
+
await this.request('POST', `/api/workers/${this.workerId}/release`, {
|
| 108 |
+
lease_epoch: this.leaseEpoch,
|
| 109 |
+
clear_run: true,
|
| 110 |
+
final_status: 'online',
|
| 111 |
+
status_reason: 'github_issues_runtime_stop',
|
| 112 |
+
approval_state: 'idle',
|
| 113 |
+
}).catch(() => undefined);
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
async heartbeat() {
|
| 117 |
+
if (!this.enabled || !this.workerId) return this.snapshot();
|
| 118 |
+
const result = await this.request<Room13WorkerClaimResponse>('POST', `/api/workers/${this.workerId}/heartbeat`, {
|
| 119 |
+
lease_epoch: this.leaseEpoch,
|
| 120 |
+
ttl_sec: 120,
|
| 121 |
+
metadata: {
|
| 122 |
+
run_id: this.runId,
|
| 123 |
+
claimed_task_id: this.claimedTaskId,
|
| 124 |
+
last_heartbeat_source: 'sin-github-issues',
|
| 125 |
+
},
|
| 126 |
+
});
|
| 127 |
+
this.leaseEpoch = Number(result?.lease_epoch || this.leaseEpoch || 0);
|
| 128 |
+
this.leaseExpiresAt = result?.lease_expires_at || this.leaseExpiresAt;
|
| 129 |
+
return this.snapshot();
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
async claimNextTask() {
|
| 133 |
+
if (!this.enabled || !this.workerId) throw new Error('room13_worker_not_registered');
|
| 134 |
+
const task = await this.request<Room13Task>('POST', '/api/tasks/claim-next', {
|
| 135 |
+
worker_id: this.workerId,
|
| 136 |
+
accepted_types: ['github_issue_dispatch'],
|
| 137 |
+
min_priority: 'normal',
|
| 138 |
+
run_id: this.runId,
|
| 139 |
+
lease_epoch: this.leaseEpoch,
|
| 140 |
+
});
|
| 141 |
+
this.claimedTaskId = String(task?.id || '').trim();
|
| 142 |
+
return task;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
async checkpoint(step: string, checkpoint: Record<string, unknown> = {}) {
|
| 146 |
+
if (!this.enabled || !this.workerId) throw new Error('room13_worker_not_registered');
|
| 147 |
+
return await this.request('POST', `/api/workers/${this.workerId}/checkpoint`, {
|
| 148 |
+
lease_epoch: this.leaseEpoch,
|
| 149 |
+
run_id: this.runId,
|
| 150 |
+
step,
|
| 151 |
+
checkpoint,
|
| 152 |
+
});
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
async completeTask(result: Record<string, unknown> = {}) {
|
| 156 |
+
if (!this.enabled || !this.claimedTaskId) throw new Error('room13_task_not_claimed');
|
| 157 |
+
const response = await this.request('PUT', `/api/tasks/${this.claimedTaskId}/complete`, result);
|
| 158 |
+
this.claimedTaskId = '';
|
| 159 |
+
return response;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
private startHeartbeatLoop() {
|
| 163 |
+
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
| 164 |
+
this.heartbeatTimer = setInterval(() => {
|
| 165 |
+
void this.heartbeat().catch(() => undefined);
|
| 166 |
+
}, 30000);
|
| 167 |
+
this.heartbeatTimer.unref();
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
private async request<T = unknown>(method: string, path: string, body?: unknown) {
|
| 171 |
+
const headers: Record<string, string> = { 'content-type': 'application/json' };
|
| 172 |
+
if (this.bearerToken) headers.Authorization = `Bearer ${this.bearerToken}`;
|
| 173 |
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
| 174 |
+
method,
|
| 175 |
+
headers,
|
| 176 |
+
body: body ? JSON.stringify(body) : undefined,
|
| 177 |
+
});
|
| 178 |
+
const text = await response.text();
|
| 179 |
+
const parsed = text ? JSON.parse(text) : {};
|
| 180 |
+
if (!response.ok) throw new Error(`room13_http_${response.status}:${JSON.stringify(parsed).slice(0, 1000)}`);
|
| 181 |
+
return parsed as T;
|
| 182 |
+
}
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
export function installGitHubIssuesWorkerRuntime(runtime: GitHubIssuesRoom13WorkerRuntime | null) {
|
| 186 |
+
currentRuntime = runtime;
|
| 187 |
+
}
|
src/runtime.ts
CHANGED
|
@@ -1,11 +1,42 @@
|
|
| 1 |
import { exec } from 'node:child_process';
|
| 2 |
import { promisify } from 'node:util';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
const execAsync = promisify(exec);
|
| 5 |
|
| 6 |
export type GitHubAgentAction =
|
| 7 |
| { action: 'agent.help' }
|
| 8 |
| { action: 'sin.github.health' }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
| { action: 'sin.github.project.orchestrate'; prompt: string; contextDir?: string }
|
| 10 |
| { action: 'sin.github.issue.manage'; prompt: string; issueNumber?: number }
|
| 11 |
| { action: 'sin.github.wiki.sync'; prompt: string; contextDir?: string }
|
|
@@ -13,8 +44,7 @@ export type GitHubAgentAction =
|
|
| 13 |
| { action: 'sin.github.gist.publish'; prompt: string; isPublic?: boolean }
|
| 14 |
| { action: 'sin.github.security.audit'; prompt: string; contextDir?: string }
|
| 15 |
| { action: 'sin.github.pr.review'; prNumber: number; contextDir?: string }
|
| 16 |
-
| { action: 'sin.github.ledger.log'; agentName: string; activityTitle: string; details: string }
|
| 17 |
-
| { action: 'sin.github.governance.report_concern'; concernType: string; details: string };
|
| 18 |
|
| 19 |
export async function executeGitHubAgentAction(action: GitHubAgentAction): Promise<unknown> {
|
| 20 |
switch (action.action) {
|
|
@@ -25,6 +55,15 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
|
|
| 25 |
mandate: 'CEO Elite GitHub Operations. Orchestrates Projects, Issues, Wikis, Discussions, Gists, Security, PR Reviews, and public Showcase Ledgers.',
|
| 26 |
actions: [
|
| 27 |
'sin.github.health',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
'sin.github.project.orchestrate',
|
| 29 |
'sin.github.issue.manage',
|
| 30 |
'sin.github.wiki.sync',
|
|
@@ -32,8 +71,7 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
|
|
| 32 |
'sin.github.gist.publish',
|
| 33 |
'sin.github.security.audit',
|
| 34 |
'sin.github.pr.review',
|
| 35 |
-
'sin.github.ledger.log'
|
| 36 |
-
'sin.github.governance.report_concern'
|
| 37 |
],
|
| 38 |
};
|
| 39 |
|
|
@@ -46,8 +84,41 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
|
|
| 46 |
team: 'Team - Coding',
|
| 47 |
status: 'Elite 2026 GitHub Operations Architect Online',
|
| 48 |
capabilities: ['projects', 'wikis', 'discussions', 'gists', 'security', 'prs', 'issues', 'ledger'],
|
|
|
|
| 49 |
};
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
case 'sin.github.project.orchestrate':
|
| 52 |
return await executeOpenCode(
|
| 53 |
`Use the GitHub CLI ('gh project create/link/item-add') to orchestrate the following project board requirements: ${action.prompt}. Ensure the board is linked to the repository and items are properly assigned.`,
|
|
@@ -91,21 +162,9 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
|
|
| 91 |
return await executeOpenCode(
|
| 92 |
`Create a new public GitHub Issue or Discussion in the repository 'Delqhi/OpenSolver-Ledger' titled "[${action.agentName}] ${action.activityTitle}". The body must contain the following details formatted in premium markdown to showcase our fleet's capabilities: \n\n${action.details}`
|
| 93 |
);
|
| 94 |
-
|
| 95 |
-
case 'sin.github.governance.report_concern':
|
| 96 |
-
return await reportSecurityConcern(action.concernType, action.details);
|
| 97 |
}
|
| 98 |
}
|
| 99 |
|
| 100 |
-
async function reportSecurityConcern(type: string, details: string) {
|
| 101 |
-
console.log(`⚠️ Security concern reported: ${type}`);
|
| 102 |
-
return {
|
| 103 |
-
ok: true,
|
| 104 |
-
status: 'incident_logged',
|
| 105 |
-
policy: 'FLEET_AUTONOMY_DOWNGRADED_BY_10_PERCENT'
|
| 106 |
-
};
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
async function executeOpenCode(prompt: string, dir?: string) {
|
| 110 |
await execAsync('python3 scripts/hf_pull_script.py').catch(() => console.warn('Warning: hf_pull_script failed. Proceeding with cached credentials.'));
|
| 111 |
|
|
@@ -123,3 +182,130 @@ async function executeOpenCode(prompt: string, dir?: string) {
|
|
| 123 |
throw new Error(`GitHub Operations Execution Failed: ${error.message}`);
|
| 124 |
}
|
| 125 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import { exec } from 'node:child_process';
|
| 2 |
import { promisify } from 'node:util';
|
| 3 |
+
import { commentIssue, closeIssue, ensureIssue } from './github.js';
|
| 4 |
+
import { createClient } from '@supabase/supabase-js';
|
| 5 |
+
import { getCurrentGitHubIssuesWorkerRuntime } from './room13-worker.js';
|
| 6 |
+
import {
|
| 7 |
+
buildDeliveryKey,
|
| 8 |
+
buildIssueKey,
|
| 9 |
+
routeIssueTriage,
|
| 10 |
+
routeLabelsToTeam,
|
| 11 |
+
TriageEnqueueSchema,
|
| 12 |
+
type TriageEnqueueInput,
|
| 13 |
+
} from './triage.js';
|
| 14 |
+
import { ISSUE_QUEUE_STATE } from './queue-state.js';
|
| 15 |
|
| 16 |
const execAsync = promisify(exec);
|
| 17 |
|
| 18 |
export type GitHubAgentAction =
|
| 19 |
| { action: 'agent.help' }
|
| 20 |
| { action: 'sin.github.health' }
|
| 21 |
+
| { action: 'sin.github.worker.register' }
|
| 22 |
+
| { action: 'sin.github.worker.status' }
|
| 23 |
+
| { action: 'sin.github.worker.claim_next' }
|
| 24 |
+
| { action: 'sin.github.worker.checkpoint'; step: string; checkpoint?: Record<string, unknown> }
|
| 25 |
+
| { action: 'sin.github.worker.complete'; result?: Record<string, unknown> }
|
| 26 |
+
| { action: 'sin.github.issue.ensure'; repo: string; title: string; body: string; labels?: string[] }
|
| 27 |
+
| { action: 'sin.github.issue.comment'; repo: string; issueNumber: number; body: string }
|
| 28 |
+
| { action: 'sin.github.issue.close'; repo: string; issueNumber: number; comment?: string }
|
| 29 |
+
| {
|
| 30 |
+
action: 'sin.github.issue.triage.enqueue';
|
| 31 |
+
repo: string;
|
| 32 |
+
issueNumber: number;
|
| 33 |
+
title: string;
|
| 34 |
+
body?: string;
|
| 35 |
+
labels?: string[];
|
| 36 |
+
assignedTeam?: string;
|
| 37 |
+
deliveryId?: string;
|
| 38 |
+
eventAction?: string;
|
| 39 |
+
}
|
| 40 |
| { action: 'sin.github.project.orchestrate'; prompt: string; contextDir?: string }
|
| 41 |
| { action: 'sin.github.issue.manage'; prompt: string; issueNumber?: number }
|
| 42 |
| { action: 'sin.github.wiki.sync'; prompt: string; contextDir?: string }
|
|
|
|
| 44 |
| { action: 'sin.github.gist.publish'; prompt: string; isPublic?: boolean }
|
| 45 |
| { action: 'sin.github.security.audit'; prompt: string; contextDir?: string }
|
| 46 |
| { action: 'sin.github.pr.review'; prNumber: number; contextDir?: string }
|
| 47 |
+
| { action: 'sin.github.ledger.log'; agentName: string; activityTitle: string; details: string };
|
|
|
|
| 48 |
|
| 49 |
export async function executeGitHubAgentAction(action: GitHubAgentAction): Promise<unknown> {
|
| 50 |
switch (action.action) {
|
|
|
|
| 55 |
mandate: 'CEO Elite GitHub Operations. Orchestrates Projects, Issues, Wikis, Discussions, Gists, Security, PR Reviews, and public Showcase Ledgers.',
|
| 56 |
actions: [
|
| 57 |
'sin.github.health',
|
| 58 |
+
'sin.github.worker.register',
|
| 59 |
+
'sin.github.worker.status',
|
| 60 |
+
'sin.github.worker.claim_next',
|
| 61 |
+
'sin.github.worker.checkpoint',
|
| 62 |
+
'sin.github.worker.complete',
|
| 63 |
+
'sin.github.issue.ensure',
|
| 64 |
+
'sin.github.issue.comment',
|
| 65 |
+
'sin.github.issue.close',
|
| 66 |
+
'sin.github.issue.triage.enqueue',
|
| 67 |
'sin.github.project.orchestrate',
|
| 68 |
'sin.github.issue.manage',
|
| 69 |
'sin.github.wiki.sync',
|
|
|
|
| 71 |
'sin.github.gist.publish',
|
| 72 |
'sin.github.security.audit',
|
| 73 |
'sin.github.pr.review',
|
| 74 |
+
'sin.github.ledger.log'
|
|
|
|
| 75 |
],
|
| 76 |
};
|
| 77 |
|
|
|
|
| 84 |
team: 'Team - Coding',
|
| 85 |
status: 'Elite 2026 GitHub Operations Architect Online',
|
| 86 |
capabilities: ['projects', 'wikis', 'discussions', 'gists', 'security', 'prs', 'issues', 'ledger'],
|
| 87 |
+
room13Worker: getCurrentGitHubIssuesWorkerRuntime()?.snapshot() || null,
|
| 88 |
};
|
| 89 |
|
| 90 |
+
case 'sin.github.worker.register':
|
| 91 |
+
return { ok: true, worker: await getCurrentGitHubIssuesWorkerRuntime()?.start() };
|
| 92 |
+
|
| 93 |
+
case 'sin.github.worker.status':
|
| 94 |
+
return { ok: true, worker: getCurrentGitHubIssuesWorkerRuntime()?.snapshot() || null };
|
| 95 |
+
|
| 96 |
+
case 'sin.github.worker.claim_next':
|
| 97 |
+
return { ok: true, task: await getCurrentGitHubIssuesWorkerRuntime()?.claimNextTask() };
|
| 98 |
+
|
| 99 |
+
case 'sin.github.worker.checkpoint':
|
| 100 |
+
return { ok: true, checkpoint: await getCurrentGitHubIssuesWorkerRuntime()?.checkpoint(action.step, action.checkpoint || {}) };
|
| 101 |
+
|
| 102 |
+
case 'sin.github.worker.complete':
|
| 103 |
+
return { ok: true, completion: await getCurrentGitHubIssuesWorkerRuntime()?.completeTask(action.result || {}) };
|
| 104 |
+
|
| 105 |
+
case 'sin.github.issue.ensure':
|
| 106 |
+
return await ensureIssue({
|
| 107 |
+
repo: action.repo,
|
| 108 |
+
title: action.title,
|
| 109 |
+
body: action.body,
|
| 110 |
+
labels: action.labels,
|
| 111 |
+
});
|
| 112 |
+
|
| 113 |
+
case 'sin.github.issue.comment':
|
| 114 |
+
return await commentIssue(action.repo, action.issueNumber, action.body);
|
| 115 |
+
|
| 116 |
+
case 'sin.github.issue.close':
|
| 117 |
+
return await closeIssue(action.repo, action.issueNumber, action.comment);
|
| 118 |
+
|
| 119 |
+
case 'sin.github.issue.triage.enqueue':
|
| 120 |
+
return await enqueueIssueTriage(action);
|
| 121 |
+
|
| 122 |
case 'sin.github.project.orchestrate':
|
| 123 |
return await executeOpenCode(
|
| 124 |
`Use the GitHub CLI ('gh project create/link/item-add') to orchestrate the following project board requirements: ${action.prompt}. Ensure the board is linked to the repository and items are properly assigned.`,
|
|
|
|
| 162 |
return await executeOpenCode(
|
| 163 |
`Create a new public GitHub Issue or Discussion in the repository 'Delqhi/OpenSolver-Ledger' titled "[${action.agentName}] ${action.activityTitle}". The body must contain the following details formatted in premium markdown to showcase our fleet's capabilities: \n\n${action.details}`
|
| 164 |
);
|
|
|
|
|
|
|
|
|
|
| 165 |
}
|
| 166 |
}
|
| 167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
async function executeOpenCode(prompt: string, dir?: string) {
|
| 169 |
await execAsync('python3 scripts/hf_pull_script.py').catch(() => console.warn('Warning: hf_pull_script failed. Proceeding with cached credentials.'));
|
| 170 |
|
|
|
|
| 182 |
throw new Error(`GitHub Operations Execution Failed: ${error.message}`);
|
| 183 |
}
|
| 184 |
}
|
| 185 |
+
|
| 186 |
+
async function enqueueIssueTriage(action: Extract<GitHubAgentAction, { action: 'sin.github.issue.triage.enqueue' }>) {
|
| 187 |
+
const input = TriageEnqueueSchema.parse(action) as TriageEnqueueInput;
|
| 188 |
+
const supabaseUrl = process.env.SUPABASE_URL || process.env.SIN_SUPABASE_URL;
|
| 189 |
+
const serviceRole = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SIN_SUPABASE_SERVICE_ROLE_KEY;
|
| 190 |
+
if (!supabaseUrl || !serviceRole) {
|
| 191 |
+
throw new Error('missing_supabase_credentials');
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
const supabase = createClient(supabaseUrl, serviceRole, { auth: { persistSession: false } });
|
| 195 |
+
const deliveryId = buildDeliveryKey(input);
|
| 196 |
+
const issueKey = buildIssueKey(input.repo, input.issueNumber);
|
| 197 |
+
const labels = input.labels || [];
|
| 198 |
+
const route = routeIssueTriage(labels, input.title, input.body || '');
|
| 199 |
+
const assignedTeam = input.assignedTeam || route.assignedTeam;
|
| 200 |
+
|
| 201 |
+
const { data: byDelivery, error: deliveryError } = await supabase
|
| 202 |
+
.from('sin_issues_pool')
|
| 203 |
+
.select('id, issue_number, repo_name, title, status, metadata, delivery_id')
|
| 204 |
+
.eq('delivery_id', deliveryId)
|
| 205 |
+
.maybeSingle();
|
| 206 |
+
if (deliveryError) throw deliveryError;
|
| 207 |
+
|
| 208 |
+
if (byDelivery) {
|
| 209 |
+
return {
|
| 210 |
+
ok: true,
|
| 211 |
+
created: false,
|
| 212 |
+
deduplicatedBy: 'delivery_id',
|
| 213 |
+
queueId: byDelivery.id,
|
| 214 |
+
issueKey,
|
| 215 |
+
status: byDelivery.status,
|
| 216 |
+
deliveryId,
|
| 217 |
+
};
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
const { data: existing, error: selectError } = await supabase
|
| 221 |
+
.from('sin_issues_pool')
|
| 222 |
+
.select('id, issue_number, repo_name, title, status, metadata, delivery_id')
|
| 223 |
+
.eq('repo_name', input.repo)
|
| 224 |
+
.eq('issue_number', input.issueNumber)
|
| 225 |
+
.maybeSingle();
|
| 226 |
+
if (selectError) throw selectError;
|
| 227 |
+
|
| 228 |
+
if (existing) {
|
| 229 |
+
const mergedMetadata = {
|
| 230 |
+
...(existing.metadata || {}),
|
| 231 |
+
last_delivery_id: deliveryId,
|
| 232 |
+
issue_key: issueKey,
|
| 233 |
+
event_action: input.eventAction || 'opened',
|
| 234 |
+
labels,
|
| 235 |
+
ingress: 'github-issues-runtime',
|
| 236 |
+
route,
|
| 237 |
+
};
|
| 238 |
+
|
| 239 |
+
const { error: updateError } = await supabase
|
| 240 |
+
.from('sin_issues_pool')
|
| 241 |
+
.update({
|
| 242 |
+
metadata: mergedMetadata,
|
| 243 |
+
delivery_id: deliveryId,
|
| 244 |
+
updated_at: new Date().toISOString(),
|
| 245 |
+
})
|
| 246 |
+
.eq('id', existing.id);
|
| 247 |
+
if (updateError) throw updateError;
|
| 248 |
+
|
| 249 |
+
return {
|
| 250 |
+
ok: true,
|
| 251 |
+
created: false,
|
| 252 |
+
deduplicatedBy: 'issue_key',
|
| 253 |
+
queueId: existing.id,
|
| 254 |
+
issueKey,
|
| 255 |
+
status: existing.status,
|
| 256 |
+
deliveryId,
|
| 257 |
+
};
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
const payload = {
|
| 261 |
+
issue_number: input.issueNumber,
|
| 262 |
+
repo_name: input.repo,
|
| 263 |
+
title: input.title,
|
| 264 |
+
body: input.body || '',
|
| 265 |
+
state: 'open',
|
| 266 |
+
assigned_team: assignedTeam,
|
| 267 |
+
assigned_agent: null,
|
| 268 |
+
status: 'pending',
|
| 269 |
+
queue_state: ISSUE_QUEUE_STATE.queued,
|
| 270 |
+
delivery_id: deliveryId,
|
| 271 |
+
issue_key: issueKey,
|
| 272 |
+
event_action: input.eventAction || 'opened',
|
| 273 |
+
metadata: {
|
| 274 |
+
delivery_id: deliveryId,
|
| 275 |
+
issue_key: issueKey,
|
| 276 |
+
event_action: input.eventAction || 'opened',
|
| 277 |
+
labels,
|
| 278 |
+
ingress: 'github-issues-runtime',
|
| 279 |
+
route,
|
| 280 |
+
},
|
| 281 |
+
};
|
| 282 |
+
|
| 283 |
+
const { data: inserted, error: insertError } = await supabase
|
| 284 |
+
.from('sin_issues_pool')
|
| 285 |
+
.insert(payload)
|
| 286 |
+
.select('id, status')
|
| 287 |
+
.single();
|
| 288 |
+
if (insertError) throw insertError;
|
| 289 |
+
|
| 290 |
+
await commentIssue(
|
| 291 |
+
input.repo,
|
| 292 |
+
input.issueNumber,
|
| 293 |
+
[
|
| 294 |
+
'AZA-SIN-Coder-•-GitHub-Issues triage complete.',
|
| 295 |
+
`Delivery: ${deliveryId}`,
|
| 296 |
+
`Assigned team: @${assignedTeam}`,
|
| 297 |
+
`Assigned agent hint: @${route.assignedAgentHint}`,
|
| 298 |
+
`Capability hint: ${route.capabilityHint}`,
|
| 299 |
+
`Queue status: ${ISSUE_QUEUE_STATE.queued}`,
|
| 300 |
+
].join('\n'),
|
| 301 |
+
);
|
| 302 |
+
|
| 303 |
+
return {
|
| 304 |
+
ok: true,
|
| 305 |
+
created: true,
|
| 306 |
+
queueId: inserted.id,
|
| 307 |
+
issueKey,
|
| 308 |
+
status: inserted.status,
|
| 309 |
+
deliveryId,
|
| 310 |
+
};
|
| 311 |
+
}
|
src/self-healing.ts
CHANGED
|
@@ -4,14 +4,14 @@ import { execFileSync } from 'node:child_process';
|
|
| 4 |
* 🚨 GLOBAL FLEET SELF-HEALING PROTOCOL (PRIORITY 0000) 🚨
|
| 5 |
* NO-SILO MANDATE: This module catches critical errors, dumps extensive logs,
|
| 6 |
* and blasts them to the fleet self-healing webhook.
|
| 7 |
-
* Hermes and SIN-GitHub-Issues will automatically take over from there.
|
| 8 |
*/
|
| 9 |
|
| 10 |
export function triggerFleetSelfHealing(error: Error, extensiveContext: Record<string, any>) {
|
| 11 |
console.error('\n🚨 CRITICAL FAILURE DETECTED. INITIATING NO-SILO SELF-HEALING PROTOCOL 🚨');
|
| 12 |
|
| 13 |
const payload = {
|
| 14 |
-
agentId: '
|
| 15 |
timestamp: new Date().toISOString(),
|
| 16 |
errorLogs: `Error: ${error.message}\nStack: ${error.stack}\nContext: ${JSON.stringify(extensiveContext, null, 2)}`,
|
| 17 |
team: 'team-coding'
|
|
|
|
| 4 |
* 🚨 GLOBAL FLEET SELF-HEALING PROTOCOL (PRIORITY 0000) 🚨
|
| 5 |
* NO-SILO MANDATE: This module catches critical errors, dumps extensive logs,
|
| 6 |
* and blasts them to the fleet self-healing webhook.
|
| 7 |
+
* Hermes and AZA-SIN-Coder-•-GitHub-Issues will automatically take over from there.
|
| 8 |
*/
|
| 9 |
|
| 10 |
export function triggerFleetSelfHealing(error: Error, extensiveContext: Record<string, any>) {
|
| 11 |
console.error('\n🚨 CRITICAL FAILURE DETECTED. INITIATING NO-SILO SELF-HEALING PROTOCOL 🚨');
|
| 12 |
|
| 13 |
const payload = {
|
| 14 |
+
agentId: 'AZA-SIN-Coder-•-GitHub-Issues',
|
| 15 |
timestamp: new Date().toISOString(),
|
| 16 |
errorLogs: `Error: ${error.message}\nStack: ${error.stack}\nContext: ${JSON.stringify(extensiveContext, null, 2)}`,
|
| 17 |
team: 'team-coding'
|
src/triage.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { z } from 'zod';
|
| 2 |
+
|
| 3 |
+
export { ISSUE_QUEUE_STATE } from './queue-state.js';
|
| 4 |
+
export type { IssueQueueState as IssueQueueStatus } from './queue-state.js';
|
| 5 |
+
|
| 6 |
+
export const TriageEnqueueSchema = z.object({
|
| 7 |
+
action: z.literal('sin.github.issue.triage.enqueue'),
|
| 8 |
+
repo: z.string().min(3),
|
| 9 |
+
issueNumber: z.number().int().positive(),
|
| 10 |
+
title: z.string().min(1),
|
| 11 |
+
body: z.string().optional(),
|
| 12 |
+
labels: z.array(z.string()).optional(),
|
| 13 |
+
assignedTeam: z.string().optional(),
|
| 14 |
+
deliveryId: z.string().optional(),
|
| 15 |
+
eventAction: z.string().optional(),
|
| 16 |
+
});
|
| 17 |
+
|
| 18 |
+
export type TriageEnqueueInput = z.infer<typeof TriageEnqueueSchema>;
|
| 19 |
+
|
| 20 |
+
export type TriageRoute = {
|
| 21 |
+
assignedTeam: string;
|
| 22 |
+
assignedAgentHint: string;
|
| 23 |
+
capabilityHint: string;
|
| 24 |
+
rationale: string;
|
| 25 |
+
};
|
| 26 |
+
|
| 27 |
+
export function buildIssueKey(repo: string, issueNumber: number) {
|
| 28 |
+
return `${repo}#${issueNumber}`;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
export function buildDeliveryKey(input: Pick<TriageEnqueueInput, 'repo' | 'issueNumber' | 'deliveryId' | 'eventAction'>) {
|
| 32 |
+
const eventAction = (input.eventAction || 'opened').trim() || 'opened';
|
| 33 |
+
const base = `${input.repo}#${input.issueNumber}:${eventAction}`;
|
| 34 |
+
return (input.deliveryId || '').trim() || `manual:${base}`;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
export function routeIssueTriage(labels: string[], title = '', body = ''): TriageRoute {
|
| 38 |
+
const normalized = labels.map((label) => label.toLowerCase());
|
| 39 |
+
const haystack = `${title} ${body}`.toLowerCase();
|
| 40 |
+
|
| 41 |
+
if (normalized.some((label) => label.includes('frontend') || label.includes('ui')) || hasAny(haystack, ['react', 'tsx', 'css', 'layout', 'component'])) {
|
| 42 |
+
return {
|
| 43 |
+
assignedTeam: 'team-coding',
|
| 44 |
+
assignedAgentHint: 'A2A-SIN-Coder-Frontend',
|
| 45 |
+
capabilityHint: 'command:render-ui',
|
| 46 |
+
rationale: 'frontend/ui-signal',
|
| 47 |
+
};
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
if (normalized.some((label) => label.includes('database') || label.includes('sql') || label.includes('supabase')) || hasAny(haystack, ['schema', 'migration', 'postgres', 'rls', 'supabase'])) {
|
| 51 |
+
return {
|
| 52 |
+
assignedTeam: 'team-coding',
|
| 53 |
+
assignedAgentHint: 'A2A-SIN-Coder-Code-Database',
|
| 54 |
+
capabilityHint: 'command:data-model',
|
| 55 |
+
rationale: 'database-signal',
|
| 56 |
+
};
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
if (normalized.some((label) => label.includes('integration') || label.includes('webhook') || label.includes('api')) || hasAny(haystack, ['webhook', 'api', 'integration', 'queue', 'dispatch'])) {
|
| 60 |
+
return {
|
| 61 |
+
assignedTeam: 'team-coding',
|
| 62 |
+
assignedAgentHint: 'A2A-SIN-Coder-Code-Integration',
|
| 63 |
+
capabilityHint: 'command:integration',
|
| 64 |
+
rationale: 'integration-signal',
|
| 65 |
+
};
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
if (normalized.some((label) => label.includes('ai') || label.includes('llm') || label.includes('mcp')) || hasAny(haystack, ['prompt', 'llm', 'agent', 'mcp', 'rag'])) {
|
| 69 |
+
return {
|
| 70 |
+
assignedTeam: 'team-coding',
|
| 71 |
+
assignedAgentHint: 'A2A-SIN-Coder-Code-AI',
|
| 72 |
+
capabilityHint: 'command:ai-runtime',
|
| 73 |
+
rationale: 'ai-signal',
|
| 74 |
+
};
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
if (normalized.some((label) => label.includes('backend') || label.includes('infra') || label.includes('ops')) || hasAny(haystack, ['backend', 'worker', 'lease', 'heartbeat', 'runtime'])) {
|
| 78 |
+
return {
|
| 79 |
+
assignedTeam: 'team-coding',
|
| 80 |
+
assignedAgentHint: 'A2A-SIN-Coder-Backend',
|
| 81 |
+
capabilityHint: 'command:backend-runtime',
|
| 82 |
+
rationale: 'backend-signal',
|
| 83 |
+
};
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
return {
|
| 87 |
+
assignedTeam: 'team-coding',
|
| 88 |
+
assignedAgentHint: 'A2A-SIN-Coder-Backend',
|
| 89 |
+
capabilityHint: 'command:implement',
|
| 90 |
+
rationale: 'default-coder-route',
|
| 91 |
+
};
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
export function routeLabelsToTeam(labels: string[], title = '', body = '') {
|
| 95 |
+
return routeIssueTriage(labels, title, body).assignedTeam;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
function hasAny(haystack: string, needles: string[]) {
|
| 99 |
+
return needles.some((needle) => haystack.includes(needle));
|
| 100 |
+
}
|