cc-viewer 1.9.8 → 1.9.10
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/README.md +1 -1
- package/cli.js +5 -3
- package/dist/assets/App-Ci9GYs24.js +2 -0
- package/dist/assets/App-D06hBGII.css +1 -0
- package/dist/assets/{MdxEditorPanel-BnbZpgDp.js → MdxEditorPanel-8fwlNHMz.js} +1 -1
- package/dist/assets/Mobile-DngSOqYr.js +1 -0
- package/dist/assets/ProxyStatsModal-CWSIELLj.js +1 -0
- package/dist/assets/{_baseUniq-CwQykUuc.js → _baseUniq-6ZLcdMmL.js} +1 -1
- package/dist/assets/{arc-EdUdBxtG.js → arc-Dirf6EZP.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-DtBIdElY.js → architectureDiagram-Q4EWVU46-BfIhmu_I.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-guNZIKkZ.js → blockDiagram-DXYQGD6D-D0y4ALi1.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-xV5vB-Z9.js → c4Diagram-AHTNJAMY-Dlfp4SUK.js} +1 -1
- package/dist/assets/{channel-DYEktNap.js → channel-CaNcU8SI.js} +1 -1
- package/dist/assets/{chunk-4BX2VUAB-ZTkItpvj.js → chunk-4BX2VUAB-ki0vHNS-.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-dYIewyyR.js → chunk-4TB4RGXK-D8yO8Iuv.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CSsPNgPX.js → chunk-55IACEB6-BvIgaNPO.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-CnMiuqzQ.js → chunk-EDXVE4YY-DF2Of_VO.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-CVpATPZ3.js → chunk-FMBD7UC4-BIw7SXs-.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-Dpq4s8dW.js → chunk-OYMX7WX6-AB76s0A0.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-Bnojh6X6.js → chunk-QZHKN3VN-CuN2LCFc.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-BYqK4Dsa.js → chunk-YZCP3GAM-D4DLBzBN.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-DLJzWgYm.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-DLJzWgYm.js +1 -0
- package/dist/assets/clone-H_VGsHn9.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-OJ7mmWyV.js → cose-bilkent-S5V4N54A-Bn485PX9.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-B1Kwd_Rk.js → dagre-KV5264BT-e4QVCf17.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-D8qrw8sp.js → diagram-5BDNPKRD-_SBFGgnf.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-ip-N4ho8.js → diagram-G4DWMVQ6-Bz1ovxLs.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-2PZaskUF.js → diagram-MMDJMWI5-B-oojW8K.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-CeAOQUZP.js → diagram-TYMM5635-CTAyNaOj.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-BCBaEYEb.js → erDiagram-SMLLAGMA-BfvKAqq2.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-CsGyIqcX.js → flowDiagram-DWJPFMVM-BpTEZEAe.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-COsj3FZ-.js → ganttDiagram-T4ZO3ILL-DUD_vkyE.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-DvQVQGJG.js → gitGraphDiagram-UUTBAWPF-DnlXcTud.js} +1 -1
- package/dist/assets/{graph-BSB9fDSP.js → graph-D4xsUKSn.js} +1 -1
- package/dist/assets/{index-DKufsAzx.js → index-84-BjpGl.js} +1 -1
- package/dist/assets/index-BDKwOnE3.js +2 -0
- package/dist/assets/{index-Bo-12bug.js → index-BniBLRtZ.js} +1 -1
- package/dist/assets/{index-BRw4Iz2O.js → index-C2Zo3KOg.js} +1 -1
- package/dist/assets/{index-BuVComcY.js → index-CWZoKT7e.js} +1 -1
- package/dist/assets/{index-eM2ih5n7.js → index-D-4EsFub.js} +1 -1
- package/dist/assets/{index-CNNAYjkF.js → index-D3KzRmkP.js} +1 -1
- package/dist/assets/{index-DXBfwPYD.js → index-NGgdum2i.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-eNucS4iW.js → infoDiagram-42DDH7IO-BbdvmCDt.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-Dxxj-gUX.js → ishikawaDiagram-UXIWVN3A-oZBOPoTO.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-yJJzVEBb.js → journeyDiagram-VCZTEJTY-DWoH0hs9.js} +1 -1
- package/dist/assets/{jszip.min-ByI0ds5u.js → jszip.min-I5y9RZhq.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-2rfTi2zw.js → kanban-definition-6JOO6SKY-BLHtjKsS.js} +1 -1
- package/dist/assets/{layout-DTmHj0Wm.js → layout-C116SNcQ.js} +1 -1
- package/dist/assets/{linear-BOA3a9FE.js → linear-Br08WCkF.js} +1 -1
- package/dist/assets/{mermaid.core-5H-NR79H.js → mermaid.core-D-4dTrvI.js} +2 -2
- package/dist/assets/{min-CpjFTEec.js → min-khs74HbH.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-B8KCjFgB.js → mindmap-definition-QFDTVHPH-C3_yItFF.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-BARy96g5.js → pieDiagram-DEJITSTG-ByCwM2_P.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-DYoTapuI.js → quadrantDiagram-34T5L4WZ-CjV65X1r.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-EeANLLK2.js → requirementDiagram-MS252O5E-DFJ_dbtV.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-DmQ-YVPj.js → sankeyDiagram-XADWPNL6-BBvXoBfj.js} +1 -1
- package/dist/assets/seqResourceLoaders-C34z9uOa.css +41 -0
- package/dist/assets/seqResourceLoaders-JJzgZZzU.js +2 -0
- package/dist/assets/{sequenceDiagram-FGHM5R23-SZtW0rYC.js → sequenceDiagram-FGHM5R23-BJM04Y3N.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-CEygsIld.js → stateDiagram-FHFEXIEX-DI2q_Kkn.js} +1 -1
- package/dist/assets/{stateDiagram-v2-QKLJ7IA2-BU1XPhBe.js → stateDiagram-v2-QKLJ7IA2-CrGC6kEY.js} +1 -1
- package/dist/assets/{timeline-definition-GMOUNBTQ-DhPBaQBt.js → timeline-definition-GMOUNBTQ-JcfRUsjD.js} +1 -1
- package/dist/assets/vendor-antd-DxEVqVhD.js +17 -0
- package/dist/assets/vendor-codemirror-CgNlkZva.js +1 -0
- package/dist/assets/{vendor-mdxeditor-Cz09a1_I.js → vendor-mdxeditor-DoreQf4A.js} +2 -2
- package/dist/assets/{vendor-qrcode-qbbntD6-.js → vendor-qrcode-q1CKtOyX.js} +1 -1
- package/dist/assets/{vendor-virtuoso-Sk8fQ4Hx.js → vendor-virtuoso-BXGe9q7E.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-NniTHxDw.js → vennDiagram-DHZGUBPP-mAHR1Ugj.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-D9SNOrDw.js → wardley-RL74JXVD-mlTq_P-4.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-DvHXKNza.js → wardleyDiagram-NUSXRM2D-BDGfajRb.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-CaiwPTQB.js → xychartDiagram-5P7HB3ND-Cf2pR1mV.js} +1 -1
- package/dist/index.html +4 -4
- package/package.json +1 -1
- package/plugins/README.md +9 -1
- package/server/interceptor.js +1 -1
- package/server/lib/builtin-model-prompts.js +1 -1
- package/server/lib/chat-queue.js +1 -1
- package/server/lib/credential-access.js +1 -1
- package/server/lib/credential-migrate.js +1 -1
- package/server/lib/error-report.js +26 -0
- package/server/lib/json-store.js +1 -1
- package/server/lib/launch-config.js +1 -1
- package/server/lib/log-watcher.js +1 -1
- package/server/lib/plugin-host.mjs +198 -0
- package/server/lib/plugin-loader.js +346 -90
- package/server/lib/plugin-manager.js +46 -2
- package/server/lib/plugin-manifest.js +329 -0
- package/server/lib/plugin-panels.js +183 -0
- package/server/lib/plugin-proxy.js +408 -0
- package/server/lib/plugin-runtime.js +775 -0
- package/server/lib/plugin-service-manager.js +463 -0
- package/server/lib/proxy/proxy-retry.js +1 -1
- package/server/lib/proxy/proxy-stats.js +1 -1
- package/server/lib/resume-watchdog.js +1 -1
- package/server/lib/same-origin.js +13 -3
- package/server/lib/sdk-manager.js +117 -23
- package/server/lib/sdk-session-index.js +1 -1
- package/server/lib/stats-worker.js +1 -1
- package/server/lib/system-prompt-files.js +1 -1
- package/server/lib/system-prompt-live.js +1 -1
- package/server/lib/system-prompt-snapshots.js +1 -1
- package/server/lib/v2/adapter.js +1 -1
- package/server/lib/v2/convert.js +1 -1
- package/server/lib/v2/jsonl-read.js +1 -1
- package/server/lib/v2/live-feed.js +1 -1
- package/server/lib/v2/meta-rows.js +1 -1
- package/server/lib/v2/resume-list.js +1 -1
- package/server/lib/v2/session-list.js +1 -1
- package/server/lib/v2/session-owner.js +1 -1
- package/server/lib/v2/v2-writer.js +1 -1
- package/server/lib/wire-compress.js +1 -1
- package/server/lib/ws-mux.js +1 -1
- package/server/proxy.js +1 -1
- package/server/pty-manager.js +1 -1
- package/server/routes/ask-perm.js +1 -1
- package/server/routes/events.js +1 -1
- package/server/routes/expert.js +1 -1
- package/server/routes/files-content.js +1 -1
- package/server/routes/files-fs.js +4 -2
- package/server/routes/misc.js +11 -0
- package/server/routes/plugin-services.js +104 -0
- package/server/routes/plugins.js +145 -17
- package/server/routes/preferences.js +1 -1
- package/server/routes/resume.js +1 -1
- package/server/routes/sdk-context.js +1 -1
- package/server/routes/sdk-mcp-status.js +1 -1
- package/server/routes/workspaces.js +1 -1
- package/server/server.js +370 -173
- package/dist/assets/App-D2zrtS4P.js +0 -2
- package/dist/assets/App-DuDeDOuX.css +0 -1
- package/dist/assets/Mobile-CU-g7cTn.js +0 -1
- package/dist/assets/ProxyStatsModal-CavWQfBA.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-ClGF33bF.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-ClGF33bF.js +0 -1
- package/dist/assets/clone-CFj55h49.js +0 -1
- package/dist/assets/index-D2maXxkC.js +0 -2
- package/dist/assets/seqResourceLoaders-DZF6ofB7.css +0 -41
- package/dist/assets/seqResourceLoaders-jOSz1x7F.js +0 -2
- package/dist/assets/vendor-antd-CS_S2mBN.js +0 -17
- package/dist/assets/vendor-codemirror-B5l-VbBO.js +0 -1
package/server/routes/plugins.js
CHANGED
|
@@ -1,17 +1,84 @@
|
|
|
1
1
|
// Plugin management routes (moved verbatim from server.js handleRequest).
|
|
2
|
+
// Write operations go through the plugin runtime's single-flight queue so service
|
|
3
|
+
// plugins are deactivated/stopped/re-spawned — never a bare loadPlugins() that would
|
|
4
|
+
// leave child processes behind.
|
|
2
5
|
import { existsSync, unlinkSync } from 'node:fs';
|
|
3
6
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
import { uploadPlugins, installPluginFromUrl } from '../lib/plugin-manager.js';
|
|
7
|
+
import { getPluginsInfo, getPluginsDir, getPluginEntries } from '../lib/plugin-loader.js';
|
|
8
|
+
import { uploadPlugins, installPluginFromUrl, deletePluginDir } from '../lib/plugin-manager.js';
|
|
9
|
+
import {
|
|
10
|
+
reloadRuntime,
|
|
11
|
+
unloadPlugin,
|
|
12
|
+
restartPlugin,
|
|
13
|
+
getRuntimePluginStatus,
|
|
14
|
+
isRuntimeStopping,
|
|
15
|
+
} from '../lib/plugin-runtime.js';
|
|
16
|
+
import { buildPanelDescriptor } from '../lib/plugin-panels.js';
|
|
6
17
|
import { SERVER_LIB } from '../_paths.js';
|
|
18
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
19
|
+
import { isAdminReq } from '../lib/is-admin.js';
|
|
20
|
+
import { isSameOriginBrowserRequest } from '../lib/same-origin.js';
|
|
21
|
+
|
|
22
|
+
// Write endpoints execute arbitrary plugin code (reload/restart), install remote files,
|
|
23
|
+
// or delete on-disk plugins. They require an admin AND a same-origin browser context:
|
|
24
|
+
// the global ACAO:* prelude would otherwise let a cross-site page drive a localhost
|
|
25
|
+
// server that trusts its socket peer. CLI/native clients (no Origin) stay allowed.
|
|
26
|
+
function rejectWrite(req, res, isLocal, parsedUrl) {
|
|
27
|
+
// Refuse during the shutdown teardown window: a reload/restart accepted here could
|
|
28
|
+
// spawn a child after onServerStopping already swept the runtime, leaking a lock file.
|
|
29
|
+
if (isRuntimeStopping()) {
|
|
30
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
31
|
+
res.end(JSON.stringify({ error: 'server is stopping' }));
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (isAdminReq(req, isLocal) && isSameOriginBrowserRequest(req, parsedUrl)) return false;
|
|
35
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
36
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin and same-origin required' }));
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function decorateWithRuntime(plugins) {
|
|
41
|
+
return plugins.map(p => {
|
|
42
|
+
// Only service plugins have a service status; lifecycle-only dir plugins also get a
|
|
43
|
+
// runtime entry, but exposing it as serviceStatus would imply a service exists.
|
|
44
|
+
if (p.type !== 'service') return p;
|
|
45
|
+
const status = getRuntimePluginStatus(p.name);
|
|
46
|
+
return status ? { ...p, serviceStatus: status } : p;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
7
49
|
|
|
8
50
|
function pluginsList(req, res) {
|
|
9
|
-
const plugins = getPluginsInfo();
|
|
51
|
+
const plugins = decorateWithRuntime(getPluginsInfo());
|
|
10
52
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
11
53
|
res.end(JSON.stringify({ plugins, pluginsDir: getPluginsDir() }));
|
|
12
54
|
}
|
|
13
55
|
|
|
14
|
-
async function pluginsDelete(req, res, parsedUrl) {
|
|
56
|
+
async function pluginsDelete(req, res, parsedUrl, isLocal) {
|
|
57
|
+
if (rejectWrite(req, res, isLocal, parsedUrl)) return;
|
|
58
|
+
const dir = parsedUrl.searchParams.get('dir');
|
|
59
|
+
if (dir) {
|
|
60
|
+
try {
|
|
61
|
+
const unloaded = await unloadPlugin(dir, 'delete');
|
|
62
|
+
if (!unloaded.ok) {
|
|
63
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
64
|
+
res.end(JSON.stringify({ error: unloaded.error || 'plugin runtime is stopping' }));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
deletePluginDir(getPluginsDir(), dir);
|
|
68
|
+
const result = await reloadRuntime();
|
|
69
|
+
if (!result.ok) {
|
|
70
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
71
|
+
res.end(JSON.stringify({ error: result.error || 'plugin runtime is stopping' }));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
75
|
+
res.end(JSON.stringify({ ok: true, plugins: decorateWithRuntime(getPluginsInfo()), pluginsDir: getPluginsDir(), generation: result.generation }));
|
|
76
|
+
} catch (err) {
|
|
77
|
+
res.writeHead(err.statusCode || 500, { 'Content-Type': 'application/json' });
|
|
78
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
15
82
|
const file = parsedUrl.searchParams.get('file');
|
|
16
83
|
if (!file || file.includes('..') || file.includes('/') || file.includes('\\')) {
|
|
17
84
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
@@ -26,39 +93,93 @@ async function pluginsDelete(req, res, parsedUrl) {
|
|
|
26
93
|
return;
|
|
27
94
|
}
|
|
28
95
|
unlinkSync(filePath);
|
|
29
|
-
await
|
|
30
|
-
|
|
96
|
+
const result = await reloadRuntime();
|
|
97
|
+
if (!result.ok) {
|
|
98
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
99
|
+
res.end(JSON.stringify({ error: result.error || 'plugin runtime is stopping' }));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
31
102
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
32
|
-
res.end(JSON.stringify({ ok: true, plugins, pluginsDir: getPluginsDir() }));
|
|
103
|
+
res.end(JSON.stringify({ ok: true, plugins: decorateWithRuntime(getPluginsInfo()), pluginsDir: getPluginsDir(), generation: result.generation }));
|
|
33
104
|
} catch (err) {
|
|
34
105
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
35
106
|
res.end(JSON.stringify({ error: err.message }));
|
|
36
107
|
}
|
|
37
108
|
}
|
|
38
109
|
|
|
39
|
-
async function pluginsReload(req, res) {
|
|
110
|
+
async function pluginsReload(req, res, parsedUrl, isLocal) {
|
|
111
|
+
if (rejectWrite(req, res, isLocal, parsedUrl)) return;
|
|
40
112
|
try {
|
|
41
|
-
|
|
42
|
-
const
|
|
113
|
+
// ?reason=disable: the UI disable toggle goes through preferences + reload, so deactivate must receive 'disable'
|
|
114
|
+
const reason = parsedUrl && parsedUrl.searchParams.get('reason');
|
|
115
|
+
const result = await reloadRuntime(reason === 'disable' ? { reason: 'disable' } : {});
|
|
116
|
+
if (!result.ok) {
|
|
117
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
118
|
+
res.end(JSON.stringify({ error: result.error || 'plugin runtime is stopping' }));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
43
121
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
44
|
-
res.end(JSON.stringify({ ok: true, plugins, pluginsDir: getPluginsDir() }));
|
|
122
|
+
res.end(JSON.stringify({ ok: true, plugins: decorateWithRuntime(getPluginsInfo()), pluginsDir: getPluginsDir(), generation: result.generation }));
|
|
123
|
+
} catch (err) {
|
|
124
|
+
reportSwallowed('plugins.reload', err);
|
|
125
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
126
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function pluginsRestart(req, res, parsedUrl, isLocal) {
|
|
131
|
+
if (rejectWrite(req, res, isLocal, parsedUrl)) return;
|
|
132
|
+
const name = parsedUrl.searchParams.get('name');
|
|
133
|
+
if (!name) {
|
|
134
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
135
|
+
res.end(JSON.stringify({ error: 'name is required' }));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const result = await restartPlugin(name);
|
|
140
|
+
res.writeHead(result.ok ? 200 : 400, { 'Content-Type': 'application/json' });
|
|
141
|
+
res.end(JSON.stringify(result));
|
|
142
|
+
} catch (err) {
|
|
143
|
+
reportSwallowed('plugins.restart', err);
|
|
144
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
145
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function pluginPanelsList(req, res) {
|
|
150
|
+
try {
|
|
151
|
+
const panels = [];
|
|
152
|
+
for (const entry of getPluginEntries()) {
|
|
153
|
+
if (entry.shape !== 'dir' || !entry.enabled || entry.loadError || !entry.panel) continue;
|
|
154
|
+
const status = getRuntimePluginStatus(entry.name);
|
|
155
|
+
panels.push(buildPanelDescriptor(entry, { serviceStatus: status }));
|
|
156
|
+
}
|
|
157
|
+
panels.sort((a, b) => a.name.localeCompare(b.name));
|
|
158
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
159
|
+
res.end(JSON.stringify({ ok: true, panels }));
|
|
45
160
|
} catch (err) {
|
|
161
|
+
reportSwallowed('plugins.panels', err);
|
|
46
162
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
47
163
|
res.end(JSON.stringify({ error: err.message }));
|
|
48
164
|
}
|
|
49
165
|
}
|
|
50
166
|
|
|
51
167
|
function pluginsUpload(req, res, parsedUrl, isLocal, deps) {
|
|
168
|
+
if (rejectWrite(req, res, isLocal, parsedUrl)) return;
|
|
52
169
|
let body = '';
|
|
53
170
|
req.on('data', chunk => { body += chunk; if (body.length > deps.MAX_POST_BODY) req.destroy(); });
|
|
54
171
|
req.on('end', async () => {
|
|
55
172
|
try {
|
|
56
173
|
const { files: fileList } = JSON.parse(body);
|
|
57
174
|
uploadPlugins(getPluginsDir(), fileList);
|
|
58
|
-
await
|
|
59
|
-
|
|
175
|
+
const result = await reloadRuntime();
|
|
176
|
+
if (!result.ok) {
|
|
177
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
178
|
+
res.end(JSON.stringify({ error: result.error || 'plugin runtime is stopping' }));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
60
181
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
61
|
-
res.end(JSON.stringify({ ok: true, plugins, pluginsDir: getPluginsDir() }));
|
|
182
|
+
res.end(JSON.stringify({ ok: true, plugins: decorateWithRuntime(getPluginsInfo()), pluginsDir: getPluginsDir(), generation: result.generation }));
|
|
62
183
|
} catch (err) {
|
|
63
184
|
const status = err.statusCode || 500;
|
|
64
185
|
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
@@ -68,6 +189,7 @@ function pluginsUpload(req, res, parsedUrl, isLocal, deps) {
|
|
|
68
189
|
}
|
|
69
190
|
|
|
70
191
|
function pluginsInstallFromUrl(req, res, parsedUrl, isLocal, deps) {
|
|
192
|
+
if (rejectWrite(req, res, isLocal, parsedUrl)) return;
|
|
71
193
|
let body = '';
|
|
72
194
|
req.on('data', chunk => { body += chunk; if (body.length > deps.MAX_POST_BODY) req.destroy(); });
|
|
73
195
|
req.on('end', async () => {
|
|
@@ -75,10 +197,14 @@ function pluginsInstallFromUrl(req, res, parsedUrl, isLocal, deps) {
|
|
|
75
197
|
const { url: fileUrl } = JSON.parse(body);
|
|
76
198
|
const extractScript = join(SERVER_LIB, 'extract-plugin-name.mjs');
|
|
77
199
|
await installPluginFromUrl(getPluginsDir(), fileUrl, extractScript);
|
|
78
|
-
await
|
|
79
|
-
|
|
200
|
+
const result = await reloadRuntime();
|
|
201
|
+
if (!result.ok) {
|
|
202
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
203
|
+
res.end(JSON.stringify({ error: result.error || 'plugin runtime is stopping' }));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
80
206
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
81
|
-
res.end(JSON.stringify({ ok: true, plugins, pluginsDir: getPluginsDir() }));
|
|
207
|
+
res.end(JSON.stringify({ ok: true, plugins: decorateWithRuntime(getPluginsInfo()), pluginsDir: getPluginsDir(), generation: result.generation }));
|
|
82
208
|
} catch (err) {
|
|
83
209
|
const status = err.statusCode || 500;
|
|
84
210
|
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
@@ -91,6 +217,8 @@ export const pluginsRoutes = [
|
|
|
91
217
|
{ method: 'GET', match: 'exact', path: '/api/plugins', handler: pluginsList },
|
|
92
218
|
{ method: 'DELETE', match: 'exact', path: '/api/plugins', handler: pluginsDelete },
|
|
93
219
|
{ method: 'POST', match: 'exact', path: '/api/plugins/reload', handler: pluginsReload },
|
|
220
|
+
{ method: 'POST', match: 'exact', path: '/api/plugins/restart', handler: pluginsRestart },
|
|
221
|
+
{ method: 'GET', match: 'exact', path: '/api/plugin-panels', handler: pluginPanelsList },
|
|
94
222
|
{ method: 'POST', match: 'exact', path: '/api/plugins/upload', handler: pluginsUpload },
|
|
95
223
|
{ method: 'POST', match: 'exact', path: '/api/plugins/install-from-url', handler: pluginsInstallFromUrl },
|
|
96
224
|
];
|
|
@@ -7,7 +7,7 @@ import { PROFILE_PATH, _defaultConfig, getActiveProfileId, getStoredRoles, isOff
|
|
|
7
7
|
import { migrateProxyProfileList, isValidRoleValue, PROXY_ROLE_KEYS } from '../lib/interceptor-core.js';
|
|
8
8
|
import { DEFAULT_RETRY_CONFIG, validateRetryConfig, resolveRetryConfig } from '../lib/proxy/proxy-retry.js';
|
|
9
9
|
import { discoverCcSwitchProviders, mergeImportedProfiles } from '../lib/ccswitch-import.js';
|
|
10
|
-
import { reportSwallowed } from '
|
|
10
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
11
11
|
import { setLang } from '../i18n.js';
|
|
12
12
|
import { reconcileVoicePackPrefs as vpReconcile } from '../lib/voice-pack-manager.js';
|
|
13
13
|
import { readClaudeProjectModel } from '../lib/context-watcher.js';
|
package/server/routes/resume.js
CHANGED
|
@@ -53,7 +53,7 @@ import { bumpWorkspacesVersion } from '../lib/file-access-policy.js';
|
|
|
53
53
|
import { isAdminReq } from '../lib/is-admin.js';
|
|
54
54
|
import { isSameOriginBrowserRequest } from '../lib/same-origin.js';
|
|
55
55
|
import { sseWrite } from '../lib/wire-compress.js';
|
|
56
|
-
import { reportSwallowed } from '
|
|
56
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
57
57
|
import { findSdkSessionByInstance, listSdkSessionInstances } from '../lib/sdk-session-index.js';
|
|
58
58
|
|
|
59
59
|
function sendJson(res, code, obj) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the automatic turn-end/compact refreshes flow over the WS broadcast instead. A
|
|
3
3
|
// `session-inactive` outcome is a NORMAL state (no turn run yet / query dead), so it
|
|
4
4
|
// returns 200 with { ok:false, reason } rather than an HTTP error.
|
|
5
|
-
import { reportSwallowed } from '
|
|
5
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
6
6
|
|
|
7
7
|
async function sdkContextUsage(req, res) {
|
|
8
8
|
try {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// pull; there is no turn-driven refresh (MCP status is not turn-correlated). A
|
|
3
3
|
// `session-inactive` outcome is a NORMAL state (no turn run yet / query dead), so it
|
|
4
4
|
// returns 200 with { ok:false, reason } rather than an HTTP error.
|
|
5
|
-
import { reportSwallowed } from '
|
|
5
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
6
6
|
|
|
7
7
|
async function sdkMcpStatus(req, res) {
|
|
8
8
|
try {
|
|
@@ -4,7 +4,7 @@ import { basename } from 'node:path';
|
|
|
4
4
|
import { initForWorkspace, resetWorkspace, getLiveLogSource, markContinuedLaunch, markForkSession, markResumeSession, isContinuedLaunch, clearScopeState } from '../interceptor.js';
|
|
5
5
|
import { LOG_DIR } from '../../findcc.js';
|
|
6
6
|
import { migrationStatus } from '../lib/v2/migrate-prompt.js';
|
|
7
|
-
import { reportSwallowed } from '
|
|
7
|
+
import { reportSwallowed } from '../lib/error-report.js';
|
|
8
8
|
|
|
9
9
|
// P2: claude continuation flags — the workspace launcher injects `-c` itself
|
|
10
10
|
// (WorkspaceList's logCount heuristic), so argv scanning in cli.js never sees
|