@aion0/forge 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RELEASE_NOTES.md +6 -6
- package/app/api/connectors/[id]/settings/route.ts +31 -37
- package/app/api/connectors/[id]/test/route.ts +260 -0
- package/app/api/connectors/install-local/route.ts +211 -0
- package/app/api/connectors/marketplace/route.ts +79 -0
- package/app/api/connectors/route.ts +41 -46
- package/app/api/jobs/route.ts +4 -0
- package/app/api/skills/install-local/route.ts +282 -0
- package/components/ConnectorsPanel.tsx +526 -211
- package/components/SettingsModal.tsx +1 -0
- package/components/SkillsPanel.tsx +42 -1
- package/lib/agents/claude-adapter.ts +4 -0
- package/lib/agents/types.ts +6 -0
- package/lib/chat/agent-loop.ts +13 -22
- package/lib/chat/protocols/http.ts +1 -1
- package/lib/chat/protocols/shell.ts +1 -1
- package/lib/chat/tool-dispatcher.ts +20 -20
- package/lib/connectors/migration.ts +110 -0
- package/lib/connectors/registry.ts +328 -0
- package/lib/connectors/sync.ts +305 -0
- package/lib/connectors/types.ts +253 -0
- package/lib/help-docs/00-overview.md +1 -0
- package/lib/help-docs/17-connectors.md +241 -189
- package/lib/help-docs/21-build-connector.md +314 -0
- package/lib/help-docs/CLAUDE.md +4 -2
- package/lib/init.ts +25 -0
- package/lib/jobs/dispatcher.ts +28 -8
- package/lib/jobs/scheduler.ts +66 -6
- package/lib/jobs/store.ts +51 -2
- package/lib/jobs/types.ts +32 -0
- package/lib/pipeline-scheduler.ts +3 -2
- package/lib/pipeline.ts +137 -15
- package/lib/plugins/registry.ts +9 -42
- package/lib/plugins/types.ts +4 -129
- package/lib/settings.ts +7 -0
- package/lib/skills.ts +27 -1
- package/lib/task-manager.ts +62 -2
- package/package.json +4 -1
- package/src/core/db/database.ts +4 -0
- package/lib/builtin-plugins/github-api.yaml +0 -93
- package/lib/builtin-plugins/gitlab.yaml +0 -860
- package/lib/builtin-plugins/mantis.probe.js +0 -176
- package/lib/builtin-plugins/mantis.yaml +0 -964
- package/lib/builtin-plugins/pmdb.yaml +0 -178
- package/lib/builtin-plugins/teams.yaml +0 -913
package/lib/task-manager.ts
CHANGED
|
@@ -44,6 +44,14 @@ function db() {
|
|
|
44
44
|
// Per-task model overrides (used by pipeline to set pipelineModel)
|
|
45
45
|
export const taskModelOverrides = new Map<string, string>();
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Per-task append-system-prompt overrides. Used by Forge job/pipeline
|
|
49
|
+
* to point the agent at specific skills for this run. Keyed by task
|
|
50
|
+
* id; lives in-process (re-applied via the pipeline state on restart
|
|
51
|
+
* since we re-create the task there).
|
|
52
|
+
*/
|
|
53
|
+
export const taskAppendSystemPromptOverrides = new Map<string, string>();
|
|
54
|
+
|
|
47
55
|
// ─── CRUD ────────────────────────────────────────────────────
|
|
48
56
|
|
|
49
57
|
export function createTask(opts: {
|
|
@@ -351,6 +359,50 @@ async function processNextTask() {
|
|
|
351
359
|
}
|
|
352
360
|
}
|
|
353
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Surface installed-connector PATs as env vars to shell tasks. Lets
|
|
364
|
+
* pipeline shell steps (push-and-mr, gh-issue-fix, ...) use the same
|
|
365
|
+
* credential the user typed into Settings → Connectors instead of
|
|
366
|
+
* relying on `glab auth login` / `gh auth login` having been run
|
|
367
|
+
* separately (and not revoked).
|
|
368
|
+
*
|
|
369
|
+
* Only well-known connectors map to env vars. Token never leaves the
|
|
370
|
+
* server — the bash child inherits the env directly.
|
|
371
|
+
*/
|
|
372
|
+
function connectorEnv(): Record<string, string> {
|
|
373
|
+
try {
|
|
374
|
+
const { getInstalledConnector } = require('./connectors/registry');
|
|
375
|
+
const out: Record<string, string> = {};
|
|
376
|
+
const gitlab = getInstalledConnector('gitlab');
|
|
377
|
+
if (gitlab?.enabled) {
|
|
378
|
+
const tok = typeof gitlab.config?.token === 'string' ? gitlab.config.token.trim() : '';
|
|
379
|
+
if (tok) {
|
|
380
|
+
// glab CLI honours GITLAB_TOKEN; HTTP libs honour CI_JOB_TOKEN-style names too,
|
|
381
|
+
// but GITLAB_TOKEN covers glab + most curl-based scripts in our pipelines.
|
|
382
|
+
out.GITLAB_TOKEN = tok;
|
|
383
|
+
if (typeof gitlab.config?.base_url === 'string' && gitlab.config.base_url) {
|
|
384
|
+
// glab uses GITLAB_URI for the API host on self-hosted instances.
|
|
385
|
+
try {
|
|
386
|
+
const u = new URL(String(gitlab.config.base_url));
|
|
387
|
+
out.GITLAB_URI = u.origin;
|
|
388
|
+
} catch {}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const gh = getInstalledConnector('github-api');
|
|
393
|
+
if (gh?.enabled) {
|
|
394
|
+
const tok = typeof gh.config?.token === 'string' ? gh.config.token.trim() : '';
|
|
395
|
+
if (tok) {
|
|
396
|
+
out.GITHUB_TOKEN = tok;
|
|
397
|
+
out.GH_TOKEN = tok; // gh CLI honours either; set both for safety.
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return out;
|
|
401
|
+
} catch {
|
|
402
|
+
return {};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
354
406
|
function executeShellTask(task: Task): Promise<void> {
|
|
355
407
|
return new Promise((resolve) => {
|
|
356
408
|
updateTaskStatus(task.id, 'running');
|
|
@@ -365,7 +417,11 @@ function executeShellTask(task: Task): Promise<void> {
|
|
|
365
417
|
const shell = process.env.SHELL && process.env.SHELL.endsWith('bash') ? process.env.SHELL : '/bin/bash';
|
|
366
418
|
const child = spawn(shell, ['-c', task.prompt], {
|
|
367
419
|
cwd: task.projectPath,
|
|
368
|
-
env: {
|
|
420
|
+
env: {
|
|
421
|
+
...process.env,
|
|
422
|
+
PATH: process.env.PATH || '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin',
|
|
423
|
+
...connectorEnv(),
|
|
424
|
+
},
|
|
369
425
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
370
426
|
});
|
|
371
427
|
|
|
@@ -433,9 +489,13 @@ function executeTask(task: Task): Promise<void> {
|
|
|
433
489
|
conversationId: task.conversationId || undefined,
|
|
434
490
|
skipPermissions: true,
|
|
435
491
|
outputFormat: adapter.config.capabilities?.supportsStreamJson ? 'stream-json' : undefined,
|
|
492
|
+
appendSystemPrompt: taskAppendSystemPromptOverrides.get(task.id),
|
|
436
493
|
});
|
|
437
494
|
|
|
438
|
-
|
|
495
|
+
// Surface connector PATs (GITLAB_TOKEN, GITHUB_TOKEN, …) so the
|
|
496
|
+
// child's Bash invocations (claude's Bash tool, gh/glab shells)
|
|
497
|
+
// pick them up automatically. Same logic as executeShellTask.
|
|
498
|
+
const env = { ...process.env, ...connectorEnv(), ...(spawnOpts.env || {}) };
|
|
439
499
|
delete env.CLAUDECODE;
|
|
440
500
|
|
|
441
501
|
updateTaskStatus(task.id, 'running');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aion0/forge",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -34,14 +34,17 @@
|
|
|
34
34
|
"@anthropic-ai/sdk": "^0.96.0",
|
|
35
35
|
"@auth/core": "^0.34.3",
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
37
|
+
"@types/adm-zip": "^0.5.8",
|
|
37
38
|
"@xterm/addon-fit": "^0.11.0",
|
|
38
39
|
"@xterm/addon-search": "^0.16.0",
|
|
39
40
|
"@xterm/addon-unicode11": "^0.9.0",
|
|
40
41
|
"@xterm/addon-webgl": "^0.19.0",
|
|
41
42
|
"@xterm/xterm": "^6.0.0",
|
|
42
43
|
"@xyflow/react": "^12.10.1",
|
|
44
|
+
"adm-zip": "^0.5.17",
|
|
43
45
|
"ai": "^6.0.116",
|
|
44
46
|
"better-sqlite3": "^12.6.2",
|
|
47
|
+
"cron-parser": "^5.5.0",
|
|
45
48
|
"esbuild": "^0.27.3",
|
|
46
49
|
"next": "^16.2.1",
|
|
47
50
|
"next-auth": "5.0.0-beta.30",
|
package/src/core/db/database.ts
CHANGED
|
@@ -34,6 +34,10 @@ function initSchema(db: Database.Database) {
|
|
|
34
34
|
migrate("ALTER TABLE skills ADD COLUMN installed_version TEXT NOT NULL DEFAULT ''");
|
|
35
35
|
migrate('ALTER TABLE skills ADD COLUMN rating REAL DEFAULT 0');
|
|
36
36
|
migrate('ALTER TABLE skills ADD COLUMN deleted_remotely INTEGER NOT NULL DEFAULT 0');
|
|
37
|
+
// 'registry' (synced from forge-skills) vs 'local' (uploaded by user).
|
|
38
|
+
// Local skills are kept across syncs (they're not in the remote registry,
|
|
39
|
+
// so the deleted_remotely housekeeping would otherwise wipe them).
|
|
40
|
+
migrate("ALTER TABLE skills ADD COLUMN source TEXT NOT NULL DEFAULT 'registry'");
|
|
37
41
|
migrate('ALTER TABLE project_pipelines ADD COLUMN last_run_at TEXT');
|
|
38
42
|
migrate('ALTER TABLE pipeline_runs ADD COLUMN dedup_key TEXT');
|
|
39
43
|
migrate("ALTER TABLE tasks ADD COLUMN agent TEXT DEFAULT 'claude'");
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
id: github-api
|
|
2
|
-
name: GitHub API
|
|
3
|
-
icon: 🐙
|
|
4
|
-
version: 0.1.0
|
|
5
|
-
author: forge
|
|
6
|
-
description: |
|
|
7
|
-
GitHub REST API connector — runs entirely server-side (no browser tab
|
|
8
|
-
needed). Set settings.token to a personal access token for private
|
|
9
|
-
repos / higher rate limits; public-only endpoints work unauthenticated.
|
|
10
|
-
|
|
11
|
-
Demonstrates the `protocol: http` runtime: the connector declares the
|
|
12
|
-
request shape and Forge issues it from the server. Templates expand
|
|
13
|
-
{settings.*} (user-supplied) and {args.*} (LLM-supplied) into url,
|
|
14
|
-
headers, query, and body.
|
|
15
|
-
|
|
16
|
-
category: connector
|
|
17
|
-
mode: server-side
|
|
18
|
-
|
|
19
|
-
settings:
|
|
20
|
-
token:
|
|
21
|
-
type: string
|
|
22
|
-
label: GitHub token (optional)
|
|
23
|
-
description: Personal access token. Leave empty for public endpoints.
|
|
24
|
-
secret: true
|
|
25
|
-
|
|
26
|
-
tools:
|
|
27
|
-
get_repo:
|
|
28
|
-
description: |
|
|
29
|
-
Fetch metadata for a GitHub repository (description, stars, default
|
|
30
|
-
branch, etc.).
|
|
31
|
-
protocol: http
|
|
32
|
-
parameters:
|
|
33
|
-
repo:
|
|
34
|
-
type: string
|
|
35
|
-
required: true
|
|
36
|
-
description: 'Repository in "owner/name" form (e.g. "anthropics/anthropic-sdk-python").'
|
|
37
|
-
request:
|
|
38
|
-
method: GET
|
|
39
|
-
url: 'https://api.github.com/repos/{args.repo}'
|
|
40
|
-
headers:
|
|
41
|
-
Accept: 'application/vnd.github+json'
|
|
42
|
-
Authorization: 'Bearer {settings.token}'
|
|
43
|
-
User-Agent: 'forge-github-connector'
|
|
44
|
-
|
|
45
|
-
list_issues:
|
|
46
|
-
description: |
|
|
47
|
-
List issues in a GitHub repository. Default returns open issues
|
|
48
|
-
(most recent first). Use state="closed" or state="all" to widen.
|
|
49
|
-
protocol: http
|
|
50
|
-
parameters:
|
|
51
|
-
repo:
|
|
52
|
-
type: string
|
|
53
|
-
required: true
|
|
54
|
-
description: 'Repository in "owner/name" form.'
|
|
55
|
-
state:
|
|
56
|
-
type: string
|
|
57
|
-
description: 'open | closed | all (default: open).'
|
|
58
|
-
per_page:
|
|
59
|
-
type: number
|
|
60
|
-
description: 'Results per page (1–100, default 30).'
|
|
61
|
-
request:
|
|
62
|
-
method: GET
|
|
63
|
-
url: 'https://api.github.com/repos/{args.repo}/issues'
|
|
64
|
-
headers:
|
|
65
|
-
Accept: 'application/vnd.github+json'
|
|
66
|
-
Authorization: 'Bearer {settings.token}'
|
|
67
|
-
User-Agent: 'forge-github-connector'
|
|
68
|
-
query:
|
|
69
|
-
state: '{args.state}'
|
|
70
|
-
per_page: '{args.per_page}'
|
|
71
|
-
|
|
72
|
-
search_repos:
|
|
73
|
-
description: |
|
|
74
|
-
Search GitHub repositories by keyword. Sorted by stars desc by
|
|
75
|
-
default. Use q to pass GitHub search qualifiers
|
|
76
|
-
(e.g. "language:go forks:>100 created:>2024").
|
|
77
|
-
protocol: http
|
|
78
|
-
parameters:
|
|
79
|
-
q:
|
|
80
|
-
type: string
|
|
81
|
-
required: true
|
|
82
|
-
description: 'Search query (GitHub search syntax).'
|
|
83
|
-
request:
|
|
84
|
-
method: GET
|
|
85
|
-
url: 'https://api.github.com/search/repositories'
|
|
86
|
-
headers:
|
|
87
|
-
Accept: 'application/vnd.github+json'
|
|
88
|
-
Authorization: 'Bearer {settings.token}'
|
|
89
|
-
User-Agent: 'forge-github-connector'
|
|
90
|
-
query:
|
|
91
|
-
q: '{args.q}'
|
|
92
|
-
sort: stars
|
|
93
|
-
order: desc
|