@pixelbyte-software/pixcode 1.34.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-docs.html +162 -9
- package/dist/assets/index-B8w57E1r.css +32 -0
- package/dist/assets/index-Djuh0wHV.js +854 -0
- package/dist/favicon.svg +8 -8
- package/dist/icons/icon-128x128.svg +9 -9
- package/dist/icons/icon-144x144.svg +9 -9
- package/dist/icons/icon-152x152.svg +9 -9
- package/dist/icons/icon-192x192.svg +9 -9
- package/dist/icons/icon-384x384.svg +9 -9
- package/dist/icons/icon-512x512.svg +9 -9
- package/dist/icons/icon-72x72.svg +9 -9
- package/dist/icons/icon-96x96.svg +9 -9
- package/dist/icons/icon-template.svg +9 -9
- package/dist/index.html +2 -2
- package/dist/logo.svg +12 -12
- package/dist/openapi.yaml +383 -1
- package/dist-server/server/claude-sdk.js +38 -7
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cli.js +12 -17
- package/dist-server/server/cli.js.map +1 -1
- package/dist-server/server/daemon-manager.js +98 -51
- package/dist-server/server/daemon-manager.js.map +1 -1
- package/dist-server/server/database/json-store.js +8 -5
- package/dist-server/server/database/json-store.js.map +1 -1
- package/dist-server/server/index.js +31 -10
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapter-registry.js +45 -19
- package/dist-server/server/modules/orchestration/a2a/adapter-registry.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js +202 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js +205 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js +205 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js +205 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js +205 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/routes.js +298 -34
- package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/task-store.js +144 -0
- package/dist-server/server/modules/orchestration/a2a/task-store.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/validator.js +16 -0
- package/dist-server/server/modules/orchestration/a2a/validator.js.map +1 -1
- package/dist-server/server/modules/orchestration/index.js +14 -0
- package/dist-server/server/modules/orchestration/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/preview/port-watcher.js +90 -0
- package/dist-server/server/modules/orchestration/preview/port-watcher.js.map +1 -0
- package/dist-server/server/modules/orchestration/preview/preview-proxy.js +58 -0
- package/dist-server/server/modules/orchestration/preview/preview-proxy.js.map +1 -0
- package/dist-server/server/modules/orchestration/preview/types.js +2 -0
- package/dist-server/server/modules/orchestration/preview/types.js.map +1 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js +37 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js.map +1 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js +68 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js.map +1 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +128 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js +2 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js +126 -0
- package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +1047 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-store.js +76 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-store.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +151 -0
- package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow.types.js +2 -0
- package/dist-server/server/modules/orchestration/workflows/workflow.types.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workspace-target.js +98 -0
- package/dist-server/server/modules/orchestration/workflows/workspace-target.js.map +1 -0
- package/dist-server/server/modules/orchestration/workspace/docker-workspace.js +122 -0
- package/dist-server/server/modules/orchestration/workspace/docker-workspace.js.map +1 -0
- package/dist-server/server/modules/orchestration/workspace/path-safety.js +48 -0
- package/dist-server/server/modules/orchestration/workspace/path-safety.js.map +1 -0
- package/dist-server/server/modules/orchestration/workspace/types.js +11 -0
- package/dist-server/server/modules/orchestration/workspace/types.js.map +1 -0
- package/dist-server/server/modules/orchestration/workspace/workspace-manager.js +80 -0
- package/dist-server/server/modules/orchestration/workspace/workspace-manager.js.map +1 -0
- package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js +96 -0
- package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js.map +1 -0
- package/dist-server/server/modules/providers/index.js +3 -0
- package/dist-server/server/modules/providers/index.js.map +1 -0
- package/dist-server/server/openai-codex.js +35 -4
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/routes/taskmaster.js +106 -89
- package/dist-server/server/routes/taskmaster.js.map +1 -1
- package/package.json +3 -1
- package/scripts/smoke/a2a-roundtrip.mjs +167 -98
- package/scripts/smoke/orchestration-api.mjs +172 -0
- package/scripts/smoke/orchestration-live-run.mjs +176 -0
- package/server/claude-sdk.js +48 -7
- package/server/cli.js +12 -17
- package/server/daemon-manager.js +90 -51
- package/server/database/db.js +794 -794
- package/server/database/json-store.js +8 -5
- package/server/index.js +40 -9
- package/server/modules/orchestration/a2a/adapter-registry.ts +108 -58
- package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +55 -49
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +284 -283
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -0
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -0
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -0
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -0
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -0
- package/server/modules/orchestration/a2a/agent-card.ts +55 -55
- package/server/modules/orchestration/a2a/auth.middleware.ts +29 -29
- package/server/modules/orchestration/a2a/bus.ts +46 -46
- package/server/modules/orchestration/a2a/routes.ts +577 -264
- package/server/modules/orchestration/a2a/task-store.ts +178 -0
- package/server/modules/orchestration/a2a/types.ts +125 -111
- package/server/modules/orchestration/a2a/validator.ts +113 -90
- package/server/modules/orchestration/index.ts +66 -26
- package/server/modules/orchestration/preview/port-watcher.ts +112 -0
- package/server/modules/orchestration/preview/preview-proxy.ts +60 -0
- package/server/modules/orchestration/preview/types.ts +19 -0
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +45 -0
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +73 -0
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +145 -0
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +29 -0
- package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -0
- package/server/modules/orchestration/workflows/workflow-runner.ts +1206 -0
- package/server/modules/orchestration/workflows/workflow-store.ts +97 -0
- package/server/modules/orchestration/workflows/workflow.routes.ts +169 -0
- package/server/modules/orchestration/workflows/workflow.types.ts +70 -0
- package/server/modules/orchestration/workflows/workspace-target.ts +120 -0
- package/server/modules/orchestration/workspace/docker-workspace.ts +135 -0
- package/server/modules/orchestration/workspace/path-safety.ts +55 -0
- package/server/modules/orchestration/workspace/types.ts +52 -0
- package/server/modules/orchestration/workspace/workspace-manager.ts +97 -0
- package/server/modules/orchestration/workspace/worktree-workspace.ts +125 -0
- package/server/modules/providers/index.ts +2 -0
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
- package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
- package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
- package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
- package/server/modules/providers/shared/provider-configs.ts +142 -142
- package/server/openai-codex.js +40 -4
- package/server/qwen-code-cli.js +395 -395
- package/server/qwen-response-handler.js +73 -73
- package/server/routes/qwen.js +27 -27
- package/server/routes/taskmaster.js +116 -91
- package/server/services/external-access.js +171 -171
- package/server/services/provider-models.js +381 -381
- package/server/services/telegram/telegram-http-client.js +130 -130
- package/server/services/vapid-keys.js +36 -36
- package/server/utils/port-access.js +209 -209
- package/dist/assets/index-B1ghfb4w.css +0 -32
- package/dist/assets/index-BvClqlMf.js +0 -852
|
@@ -29,7 +29,7 @@ import path from 'node:path';
|
|
|
29
29
|
const CURRENT_VERSION = 1;
|
|
30
30
|
|
|
31
31
|
// Tables the store manages — empty arrays on a fresh file.
|
|
32
|
-
const EMPTY_STORE = () => ({
|
|
32
|
+
const EMPTY_STORE = (extraTables = {}) => ({
|
|
33
33
|
_version: CURRENT_VERSION,
|
|
34
34
|
_sequences: {
|
|
35
35
|
users: 0,
|
|
@@ -37,6 +37,7 @@ const EMPTY_STORE = () => ({
|
|
|
37
37
|
user_credentials: 0,
|
|
38
38
|
vapid_keys: 0,
|
|
39
39
|
push_subscriptions: 0,
|
|
40
|
+
...Object.fromEntries(Object.keys(extraTables).map((k) => [k, 0])),
|
|
40
41
|
},
|
|
41
42
|
users: [],
|
|
42
43
|
api_keys: [],
|
|
@@ -48,12 +49,14 @@ const EMPTY_STORE = () => ({
|
|
|
48
49
|
app_config: [], // each row: { key, value, created_at }
|
|
49
50
|
telegram_config: [], // 0 or 1 row: { id=1, bot_token, bot_username, updated_at }
|
|
50
51
|
telegram_links: [], // each row: { user_id, chat_id, ... }
|
|
52
|
+
...Object.fromEntries(Object.entries(extraTables).map(([k, v]) => [k, v ?? []])),
|
|
51
53
|
});
|
|
52
54
|
|
|
53
55
|
export class JsonStore {
|
|
54
|
-
constructor(filePath) {
|
|
56
|
+
constructor(filePath, extraTables = {}) {
|
|
55
57
|
this.filePath = filePath;
|
|
56
58
|
this.tmpPath = `${filePath}.tmp`;
|
|
59
|
+
this.extraTables = extraTables;
|
|
57
60
|
this.data = null;
|
|
58
61
|
this._ensureLoaded();
|
|
59
62
|
}
|
|
@@ -69,7 +72,7 @@ export class JsonStore {
|
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
if (!fs.existsSync(this.filePath)) {
|
|
72
|
-
this.data = EMPTY_STORE();
|
|
75
|
+
this.data = EMPTY_STORE(this.extraTables);
|
|
73
76
|
this._flush();
|
|
74
77
|
return;
|
|
75
78
|
}
|
|
@@ -79,7 +82,7 @@ export class JsonStore {
|
|
|
79
82
|
const parsed = JSON.parse(raw);
|
|
80
83
|
// Fill missing keys from EMPTY_STORE so adding a new "table" in a
|
|
81
84
|
// later schema doesn't crash a fresh deploy reading an old file.
|
|
82
|
-
this.data = { ...EMPTY_STORE(), ...parsed };
|
|
85
|
+
this.data = { ...EMPTY_STORE(this.extraTables), ...parsed };
|
|
83
86
|
// Ensure each well-known array key is actually an array — defends
|
|
84
87
|
// against a hand-edited file that set one to null or an object.
|
|
85
88
|
const empty = EMPTY_STORE();
|
|
@@ -96,7 +99,7 @@ export class JsonStore {
|
|
|
96
99
|
const backup = `${this.filePath}.corrupt-${Date.now()}`;
|
|
97
100
|
console.error(`[JsonStore] Failed to read ${this.filePath}: ${err.message}. Backing up to ${backup}.`);
|
|
98
101
|
try { fs.renameSync(this.filePath, backup); } catch { /* noop */ }
|
|
99
|
-
this.data = EMPTY_STORE();
|
|
102
|
+
this.data = EMPTY_STORE(this.extraTables);
|
|
100
103
|
this._flush();
|
|
101
104
|
}
|
|
102
105
|
}
|
package/server/index.js
CHANGED
|
@@ -75,6 +75,14 @@ import {
|
|
|
75
75
|
createA2ARouter,
|
|
76
76
|
adapterRegistry,
|
|
77
77
|
ClaudeCodeA2AAdapter,
|
|
78
|
+
CodexA2AAdapter,
|
|
79
|
+
CursorA2AAdapter,
|
|
80
|
+
GeminiA2AAdapter,
|
|
81
|
+
OpenCodeA2AAdapter,
|
|
82
|
+
QwenA2AAdapter,
|
|
83
|
+
createPreviewProxyRouter,
|
|
84
|
+
createOrchestrationTaskRouter,
|
|
85
|
+
createWorkflowRouter,
|
|
78
86
|
} from './modules/orchestration/index.js';
|
|
79
87
|
import networkRoutes from './routes/network.js';
|
|
80
88
|
import telegramRoutes from './routes/telegram.js';
|
|
@@ -383,7 +391,15 @@ app.use('/api/providers', authenticateToken, providerRoutes);
|
|
|
383
391
|
|
|
384
392
|
// A2A protocol router — has its own auth middleware, do NOT wrap with authenticateToken
|
|
385
393
|
adapterRegistry.register(new ClaudeCodeA2AAdapter());
|
|
394
|
+
adapterRegistry.register(new CodexA2AAdapter());
|
|
395
|
+
adapterRegistry.register(new CursorA2AAdapter());
|
|
396
|
+
adapterRegistry.register(new GeminiA2AAdapter());
|
|
397
|
+
adapterRegistry.register(new QwenA2AAdapter());
|
|
398
|
+
adapterRegistry.register(new OpenCodeA2AAdapter());
|
|
386
399
|
app.use('/a2a', createA2ARouter());
|
|
400
|
+
app.use('/preview', authenticateToken, createPreviewProxyRouter());
|
|
401
|
+
app.use('/api/orchestration', authenticateToken, createOrchestrationTaskRouter());
|
|
402
|
+
app.use('/api/orchestration', authenticateToken, createWorkflowRouter());
|
|
387
403
|
|
|
388
404
|
// Network discovery / QR endpoints (protected)
|
|
389
405
|
app.use('/api/network', authenticateToken, networkRoutes);
|
|
@@ -2831,6 +2847,7 @@ const SERVER_PORT = process.env.SERVER_PORT || 3001;
|
|
|
2831
2847
|
const HOST = process.env.HOST || '0.0.0.0';
|
|
2832
2848
|
const DISPLAY_HOST = getConnectableHost(HOST);
|
|
2833
2849
|
const VITE_PORT = process.env.VITE_PORT || 5173;
|
|
2850
|
+
const SEPARATE_FRONTEND = process.env.PIXCODE_SEPARATE_FRONTEND === '1';
|
|
2834
2851
|
|
|
2835
2852
|
async function isPortOpen(port, timeoutMs = 800) {
|
|
2836
2853
|
return await new Promise((resolve) => {
|
|
@@ -2882,7 +2899,17 @@ function printSystemDaemonActiveNotice(port) {
|
|
|
2882
2899
|
console.log(`${c.info('[INFO]')} Logs: ${c.bright(logsCommand)}`);
|
|
2883
2900
|
}
|
|
2884
2901
|
|
|
2885
|
-
function
|
|
2902
|
+
function daemonFrontendArgs() {
|
|
2903
|
+
return SEPARATE_FRONTEND
|
|
2904
|
+
? ['--frontend-port', String(VITE_PORT)]
|
|
2905
|
+
: ['--single-port'];
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
function daemonInstallArgs(mode) {
|
|
2909
|
+
return ['install', '--mode', mode, '--port', String(SERVER_PORT), ...daemonFrontendArgs()];
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
function printUserDaemonActiveNotice(port, frontendPort, frontendEnabled = SEPARATE_FRONTEND) {
|
|
2886
2913
|
const effectivePort = Number(port) || 3001;
|
|
2887
2914
|
const effectiveFrontendPort = Number(frontendPort) || 5173;
|
|
2888
2915
|
const statusCommand = buildDaemonCliCommand(
|
|
@@ -2898,8 +2925,10 @@ function printUserDaemonActiveNotice(port, frontendPort) {
|
|
|
2898
2925
|
DAEMON_COMMAND_CONTEXT
|
|
2899
2926
|
);
|
|
2900
2927
|
console.log(`${c.ok('[OK]')} User daemon is active for this account.`);
|
|
2901
|
-
console.log(`${c.info('[INFO]')}
|
|
2902
|
-
|
|
2928
|
+
console.log(`${c.info('[INFO]')} App URL: ${c.bright(`http://localhost:${effectivePort}`)}`);
|
|
2929
|
+
if (frontendEnabled) {
|
|
2930
|
+
console.log(`${c.info('[INFO]')} Frontend: ${c.bright(`http://localhost:${effectiveFrontendPort}`)}`);
|
|
2931
|
+
}
|
|
2903
2932
|
console.log(`${c.info('[INFO]')} Status: ${c.bright(statusCommand)}`);
|
|
2904
2933
|
console.log(`${c.info('[INFO]')} Stop: ${c.bright(stopCommand)}`);
|
|
2905
2934
|
console.log(`${c.info('[INFO]')} Logs: ${c.bright(logsCommand)}`);
|
|
@@ -2919,8 +2948,8 @@ async function maybeAutoDaemonBootstrapFromIndex() {
|
|
|
2919
2948
|
|
|
2920
2949
|
process.env.PIXCODE_DAEMON_ATTEMPTED = '1';
|
|
2921
2950
|
|
|
2922
|
-
const systemArgs =
|
|
2923
|
-
const userArgs =
|
|
2951
|
+
const systemArgs = daemonInstallArgs('system');
|
|
2952
|
+
const userArgs = daemonInstallArgs('user');
|
|
2924
2953
|
|
|
2925
2954
|
try {
|
|
2926
2955
|
console.log(`${c.info('[INFO]')} Linux detected. Enforcing system daemon mode for Pixcode...`);
|
|
@@ -2944,7 +2973,7 @@ async function maybeAutoDaemonBootstrapFromIndex() {
|
|
|
2944
2973
|
{
|
|
2945
2974
|
subcommand: 'install',
|
|
2946
2975
|
mode: 'system',
|
|
2947
|
-
extraArgs: ['--port', String(SERVER_PORT),
|
|
2976
|
+
extraArgs: ['--port', String(SERVER_PORT), ...daemonFrontendArgs()],
|
|
2948
2977
|
},
|
|
2949
2978
|
DAEMON_COMMAND_CONTEXT
|
|
2950
2979
|
);
|
|
@@ -2978,7 +3007,7 @@ async function maybeAutoDaemonBootstrapFromIndex() {
|
|
|
2978
3007
|
{
|
|
2979
3008
|
subcommand: 'install',
|
|
2980
3009
|
mode: 'system',
|
|
2981
|
-
extraArgs: ['--port', String(SERVER_PORT),
|
|
3010
|
+
extraArgs: ['--port', String(SERVER_PORT), ...daemonFrontendArgs()],
|
|
2982
3011
|
},
|
|
2983
3012
|
DAEMON_COMMAND_CONTEXT
|
|
2984
3013
|
);
|
|
@@ -2986,7 +3015,7 @@ async function maybeAutoDaemonBootstrapFromIndex() {
|
|
|
2986
3015
|
{
|
|
2987
3016
|
subcommand: 'install',
|
|
2988
3017
|
mode: 'user',
|
|
2989
|
-
extraArgs: ['--port', String(SERVER_PORT),
|
|
3018
|
+
extraArgs: ['--port', String(SERVER_PORT), ...daemonFrontendArgs()],
|
|
2990
3019
|
},
|
|
2991
3020
|
DAEMON_COMMAND_CONTEXT
|
|
2992
3021
|
);
|
|
@@ -3054,7 +3083,9 @@ async function startServer() {
|
|
|
3054
3083
|
console.log(`${c.info('[INFO]')} To run in production mode, go to http://${DISPLAY_HOST}:${SERVER_PORT}`);
|
|
3055
3084
|
}
|
|
3056
3085
|
|
|
3057
|
-
|
|
3086
|
+
if (SEPARATE_FRONTEND) {
|
|
3087
|
+
console.log(`${c.info('[INFO]')} To run in development mode with hot-module replacement, go to http://${DISPLAY_HOST}:${VITE_PORT}`);
|
|
3088
|
+
}
|
|
3058
3089
|
|
|
3059
3090
|
server.listen(SERVER_PORT, HOST, async () => {
|
|
3060
3091
|
const appInstallPath = APP_ROOT;
|
|
@@ -1,58 +1,108 @@
|
|
|
1
|
-
// server/modules/orchestration/a2a/adapter-registry.ts
|
|
2
|
-
// In-process registry mapping adapter ids to AbstractA2AAdapter
|
|
3
|
-
// instances. Resolution supports three id forms:
|
|
4
|
-
// - "claude-code" explicit
|
|
5
|
-
// - "skill:<skillId>" first REGISTERED adapter advertising that skill
|
|
6
|
-
// (Map iteration is insertion-ordered per ES spec).
|
|
7
|
-
// - "auto" first registered adapter (
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
import type { AbstractA2AAdapter } from '@/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js';
|
|
11
|
-
import type { AgentCard } from '@/modules/orchestration/a2a/types.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
1
|
+
// server/modules/orchestration/a2a/adapter-registry.ts
|
|
2
|
+
// In-process registry mapping adapter ids to AbstractA2AAdapter
|
|
3
|
+
// instances. Resolution supports three id forms:
|
|
4
|
+
// - "claude-code" explicit
|
|
5
|
+
// - "skill:<skillId>" first REGISTERED adapter advertising that skill
|
|
6
|
+
// (Map iteration is insertion-ordered per ES spec).
|
|
7
|
+
// - "auto" first registered adapter (deterministic fallback
|
|
8
|
+
// until smarter routing arrives in a later plan)
|
|
9
|
+
|
|
10
|
+
import type { AbstractA2AAdapter } from '@/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js';
|
|
11
|
+
import type { AgentCard } from '@/modules/orchestration/a2a/types.js';
|
|
12
|
+
|
|
13
|
+
interface ResolveAdapterOptions {
|
|
14
|
+
preferredAdapterId?: string;
|
|
15
|
+
preferredProvider?: string;
|
|
16
|
+
preferredSkillId?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class AdapterRegistry {
|
|
20
|
+
// Map iteration order is insertion-ordered (ES spec); auto and skill: resolution depend on this.
|
|
21
|
+
private readonly byId = new Map<string, AbstractA2AAdapter>();
|
|
22
|
+
|
|
23
|
+
register(adapter: AbstractA2AAdapter): void {
|
|
24
|
+
if (this.byId.has(adapter.id)) {
|
|
25
|
+
throw new Error(`A2A adapter already registered: ${adapter.id}`);
|
|
26
|
+
}
|
|
27
|
+
this.byId.set(adapter.id, adapter);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get(id: string): AbstractA2AAdapter | undefined {
|
|
31
|
+
return this.byId.get(id);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
resolve(idOrSelector: string, options: ResolveAdapterOptions = {}): AbstractA2AAdapter | undefined {
|
|
35
|
+
const normalizedSelector = idOrSelector.trim();
|
|
36
|
+
if (!normalizedSelector) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (normalizedSelector === 'auto') {
|
|
41
|
+
return this.pickPreferred(this.list(), options);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (normalizedSelector.startsWith('skill:')) {
|
|
45
|
+
const skill = normalizedSelector.slice('skill:'.length);
|
|
46
|
+
const matches = this.list().filter((adapter) =>
|
|
47
|
+
adapter.agentCard.skills.some((s) => s.id === skill),
|
|
48
|
+
);
|
|
49
|
+
if (matches.length === 0) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
return this.pickPreferred(matches, {
|
|
53
|
+
...options,
|
|
54
|
+
preferredSkillId: options.preferredSkillId ?? skill,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return this.byId.get(normalizedSelector);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
list(): AbstractA2AAdapter[] {
|
|
62
|
+
return [...this.byId.values()];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
agentCards(): AgentCard[] {
|
|
66
|
+
return this.list().map((a) => a.agentCard);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private pickPreferred(
|
|
70
|
+
adapters: AbstractA2AAdapter[],
|
|
71
|
+
options: ResolveAdapterOptions,
|
|
72
|
+
): AbstractA2AAdapter | undefined {
|
|
73
|
+
const {
|
|
74
|
+
preferredAdapterId,
|
|
75
|
+
preferredProvider,
|
|
76
|
+
preferredSkillId,
|
|
77
|
+
} = options;
|
|
78
|
+
|
|
79
|
+
if (preferredAdapterId) {
|
|
80
|
+
const byAdapterId = adapters.find((adapter) => adapter.id === preferredAdapterId);
|
|
81
|
+
if (byAdapterId) {
|
|
82
|
+
return byAdapterId;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (preferredProvider) {
|
|
87
|
+
const normalizedProvider = preferredProvider.trim().toLowerCase();
|
|
88
|
+
const byProvider = adapters.find((adapter) => adapter.id === normalizedProvider);
|
|
89
|
+
if (byProvider) {
|
|
90
|
+
return byProvider;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (preferredSkillId) {
|
|
95
|
+
const bySkill = adapters.find((adapter) =>
|
|
96
|
+
adapter.agentCard.skills.some((skill) => skill.id === preferredSkillId),
|
|
97
|
+
);
|
|
98
|
+
if (bySkill) {
|
|
99
|
+
return bySkill;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return adapters[0];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const adapterRegistry = new AdapterRegistry();
|
|
108
|
+
export type { AdapterRegistry, ResolveAdapterOptions };
|
|
@@ -1,49 +1,55 @@
|
|
|
1
|
-
// server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts
|
|
2
|
-
// Base class every CLI adapter extends. Adapters wrap the
|
|
3
|
-
// existing per-CLI runtime files (claude-sdk.js, openai-codex.js, ...)
|
|
4
|
-
// and translate between A2A messages and the CLI's native I/O.
|
|
5
|
-
|
|
6
|
-
import { a2aBus } from '@/modules/orchestration/a2a/bus.js';
|
|
7
|
-
import type {
|
|
8
|
-
AgentCard,
|
|
9
|
-
Artifact,
|
|
10
|
-
Message,
|
|
11
|
-
Task,
|
|
12
|
-
TaskError,
|
|
13
|
-
TaskState,
|
|
14
|
-
} from '@/modules/orchestration/a2a/types.js';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
1
|
+
// server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts
|
|
2
|
+
// Base class every CLI adapter extends. Adapters wrap the
|
|
3
|
+
// existing per-CLI runtime files (claude-sdk.js, openai-codex.js, ...)
|
|
4
|
+
// and translate between A2A messages and the CLI's native I/O.
|
|
5
|
+
|
|
6
|
+
import { a2aBus } from '@/modules/orchestration/a2a/bus.js';
|
|
7
|
+
import type {
|
|
8
|
+
AgentCard,
|
|
9
|
+
Artifact,
|
|
10
|
+
Message,
|
|
11
|
+
Task,
|
|
12
|
+
TaskError,
|
|
13
|
+
TaskState,
|
|
14
|
+
} from '@/modules/orchestration/a2a/types.js';
|
|
15
|
+
import type { WorkspaceHandle } from '@/modules/orchestration/workspace/types.js';
|
|
16
|
+
|
|
17
|
+
export interface AdapterContext {
|
|
18
|
+
/** Isolated execution workspace for the task. */
|
|
19
|
+
workspace: WorkspaceHandle;
|
|
20
|
+
/** Compatibility alias while legacy adapters still accept cwd directly. */
|
|
21
|
+
cwd: string;
|
|
22
|
+
/** pixcode permission mode passed through to the underlying CLI. */
|
|
23
|
+
permissionMode?: string;
|
|
24
|
+
/** Provider model selected by the user in Pixcode. */
|
|
25
|
+
model?: string;
|
|
26
|
+
/** Provider-specific tool / permission settings from Pixcode Settings. */
|
|
27
|
+
toolsSettings?: Record<string, unknown>;
|
|
28
|
+
/** Optional parent task id when this adapter is invoked inside a workflow. */
|
|
29
|
+
parentTaskId?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TaskHandle {
|
|
33
|
+
cancel(): Promise<void>;
|
|
34
|
+
finished: Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export abstract class AbstractA2AAdapter {
|
|
38
|
+
abstract readonly id: string;
|
|
39
|
+
abstract readonly agentCard: AgentCard;
|
|
40
|
+
|
|
41
|
+
abstract submitTask(task: Task, ctx: AdapterContext): Promise<TaskHandle>;
|
|
42
|
+
abstract cancelTask(taskId: string): Promise<void>;
|
|
43
|
+
|
|
44
|
+
protected emitState(taskId: string, state: TaskState, error?: TaskError): void {
|
|
45
|
+
a2aBus.publish({ kind: 'task-state', taskId, state, error });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected emitMessage(taskId: string, message: Message): void {
|
|
49
|
+
a2aBus.publish({ kind: 'message', taskId, message });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected emitArtifact(taskId: string, artifact: Artifact): void {
|
|
53
|
+
a2aBus.publish({ kind: 'artifact', taskId, artifact });
|
|
54
|
+
}
|
|
55
|
+
}
|