@xopcai/xopc 0.0.283 → 0.0.285
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-iPtG94qr.js → activity-store-B0BTIk9j.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DQ74xqLi.js → agent-avatar-dicebear-Dc-0QZTQ.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CcmqK1Sc.js +1 -0
- package/dist/gateway/static/root/assets/agents-B_7PVt7S.js +1 -0
- package/dist/gateway/static/root/assets/api-COG_Tzpv.js +1 -0
- package/dist/gateway/static/root/assets/{api-KMJzMqvZ.js → api-Coly9ab6.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-B42TpqIb.js → app-management-settings-panel-TWBO-msg.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-D9Lfe7Sk.js → appearance-settings-CpTZ2KuT.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-6qxxKFsK.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BdmQwj4x.js → archive-plugin-z_u6alob.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-B4S0_nji.js → attachment-load-C2nS04TC.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-B3TmHNjQ.js → automations-page-aIBsw9zR.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BRQlU4qk.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-B3cXF_DP.js → binary-plugins-CGmXoZnl.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-05zyBXBe.js → block-editor-CtvzCZhC.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-BTIufVbM.js → browser-automation-inputs-BOTU1isH.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-DRBA9nwe.js → browser-automations-page-BwU5V8J0.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-DDjbDeHQ.js +8 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DM1Bcf1x.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-Bq36CUxL.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-DMYQNs-J.js → channels-status-swr-Dfi0Desh.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-Dx5KQyo5.js → chat-terminal-dock-B0MvcO6j.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-L8JehrxF.js +2 -0
- package/dist/gateway/static/root/assets/{date-picker-CkDROZoe.js → date-picker-DXOvbHCr.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-Bl8HcvzL.js → dependency-picker-BEnC-eS0.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-BcknAjbW.js → desktop-pet-DtPNvznL.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BuCpXQPm.js → desktop-pet-settings-CYyjcSn6.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-BPMGvAKE.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-qRpb2FFa.js → extension-debug-page-H_aPMGXW.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-C7gs9wu4.js → extension-page-C1JnpeMt.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CyJP1CMZ.js → extension-settings-page-C75kCOqe.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Cpmyrr6j.js → gateway-config-swr-G2lQt7Ak.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-BCF732TU.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DoiPeb65.js → gateway-startup-retry-GP31PUrG.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CV6Dolcn.js → heartbeat-settings-C7fjiowt.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-DZXeXdUL.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-CqjHWl2T.js → image-generation-api-CKFhfHSw.js} +1 -1
- package/dist/gateway/static/root/assets/imports-page-GROumhj8.js +1 -0
- package/dist/gateway/static/root/assets/{index-CHgOG1aR.js → index-ChIrvv3t.js} +47 -47
- package/dist/gateway/static/root/assets/index-R1VNlHjj.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B3XqA41D.js → keyboard-shortcuts-settings-zcI822m_.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CAEKGTAg.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-BcIVYp0J.js → local-apps-page-BtgDJ92Q.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-1urrBBCQ.js → locale-store-DlOv7896.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DHZ4BEkG.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-DNFCdgzR.js → management-settings-DasZxCyD.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-BZmcFIWa.js → markdown-view-6oYdBahT.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BDxNhoBC.js → media-plugins-CxthbBvk.js} +1 -1
- package/dist/gateway/static/root/assets/messages-Ls1Aaiqd.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-BcWq3ddw.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-DfZ8QWyv.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-agH3a2PI.js → page-tabs-BG39KidE.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-XEZ7zDOP.js → preview-open-alternatives-Bevpbq9f.js} +1 -1
- package/dist/gateway/static/root/assets/proactive-page-D2U_xQaS.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-lXAbj85Z.js → product-open-page-Bi1seZpM.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CzlGTW4F.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-mQsM-TsP.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-CxQstD00.js → registry-api-D0ddwBFj.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-Cb56JcO1.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DErKZlVJ.js → runtime-tools-settings-panel-Wkru8_My.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-DhCmJQVJ.js → schema-form-CSMRzj9Y.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Hj9uFcIO.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CV4-_EVA.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-Dg6chotg.js → settings-form-section-wcAdCkK8.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-LyuN5N3M.js → settings-page-BcQGAnCs.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DzxmsaQG.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-CZvmf4Ob.js → share-preview-page-DQocUl-1.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-xlJh1ccG.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-wSXJRSxX.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-AmqtBJo7.js +2 -0
- package/dist/gateway/static/root/assets/{skills-page.utils-Eu0WVHTS.js → skills-page.utils-DtlfCgJp.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DQKkM7B2.js → system-settings-panel-Ct698Nf-.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-sQpwq5-c.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-Dc5s20V3.js → theme-store-ng8KJsAT.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-TKQpPVd6.js → tunnel-api-Boajol0M.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-CkVlrFk1.js → use-autosave-BSyxRHt2.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-DIEHnAER.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-B12fFN-L.js → voice-api-key-field-SE3OQI1s.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-Mk78BrpP.js → voice-config-api-VNuCmdFe.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CT9Zy36i.js → work-discovery-overlay-Dn1vy2oq.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BwefQliE.js → workflow-run-setup-panel-BJEfGY-k.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DgRNIyr7.js +6 -0
- package/dist/gateway/static/root/index.html +10 -10
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/proactive.js +13 -4
- package/dist/src/agent/coding/repository-instructions.js +1 -1
- package/dist/src/agent/coding/workspace-revision.js +1 -1
- package/dist/src/agent/commands/command-isolation.js +1 -1
- package/dist/src/agent/tools/factory.js +7 -3
- package/dist/src/agent/tools/review-workspace.js +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +10 -2
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-manifest.js +4 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +3 -0
- package/dist/src/cli/commands/import.d.ts +2 -0
- package/dist/src/cli/commands/import.js +78 -0
- package/dist/src/discussions/action-tasks.js +1 -1
- package/dist/src/discussions/edits.js +1 -1
- package/dist/src/discussions/index.js +1 -1
- package/dist/src/discussions/organizer.js +1 -1
- package/dist/src/discussions/recording.js +1 -1
- package/dist/src/discussions/sealer.js +1 -1
- package/dist/src/discussions/service.js +2 -2
- package/dist/src/endpoint-tools/invocation-service.d.ts +2 -0
- package/dist/src/endpoint-tools/invocation-service.js +48 -19
- package/dist/src/gateway/heartbeat/check-store.d.ts +18 -0
- package/dist/src/gateway/heartbeat/check-store.js +73 -0
- package/dist/src/gateway/heartbeat/service.d.ts +12 -3
- package/dist/src/gateway/heartbeat/service.js +61 -44
- package/dist/src/gateway/hono/routes/discussions.js +2 -2
- package/dist/src/gateway/hono/routes/imports.d.ts +3 -0
- package/dist/src/gateway/hono/routes/imports.js +56 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/proactive-control.js +2 -1
- package/dist/src/gateway/service.d.ts +7 -0
- package/dist/src/gateway/service.js +26 -9
- package/dist/src/imports/compatibility.d.ts +7 -0
- package/dist/src/imports/compatibility.js +174 -0
- package/dist/src/imports/contextImport.d.ts +3 -0
- package/dist/src/imports/contextImport.js +56 -0
- package/dist/src/imports/files.d.ts +13 -0
- package/dist/src/imports/files.js +77 -0
- package/dist/src/imports/importService.d.ts +50 -0
- package/dist/src/imports/importService.js +414 -0
- package/dist/src/imports/inventory.d.ts +11 -0
- package/dist/src/imports/inventory.js +202 -0
- package/dist/src/imports/planner.d.ts +11 -0
- package/dist/src/imports/planner.js +98 -0
- package/dist/src/imports/productImport.d.ts +10 -0
- package/dist/src/imports/productImport.js +241 -0
- package/dist/src/imports/runtime.d.ts +5 -0
- package/dist/src/imports/runtime.js +61 -0
- package/dist/src/imports/scanner.d.ts +14 -0
- package/dist/src/imports/scanner.js +159 -0
- package/dist/src/imports/secrets.d.ts +2 -0
- package/dist/src/imports/secrets.js +9 -0
- package/dist/src/imports/sources.d.ts +37 -0
- package/dist/src/imports/sources.js +75 -0
- package/dist/src/imports/types.d.ts +144 -0
- package/dist/src/imports/types.js +11 -0
- package/dist/src/infra/background-task.d.ts +2 -0
- package/dist/src/infra/background-task.js +25 -0
- package/dist/src/infra/process-diagnostics.d.ts +5 -0
- package/dist/src/infra/process-diagnostics.js +97 -0
- package/dist/src/infra/unhandled-rejections.js +6 -3
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/knowledge/ingestion-service.js +1 -0
- package/dist/src/knowledge-memory/repository.js +4 -2
- package/dist/src/media-shared/http/ssrf-guard.js +1 -1
- package/dist/src/notifications/proactive-policy.js +7 -5
- package/dist/src/proactive/execution/authorization.d.ts +2 -0
- package/dist/src/proactive/execution/authorization.js +10 -1
- package/dist/src/proactive/execution/context.js +1 -0
- package/dist/src/proactive/execution/repository.d.ts +2 -0
- package/dist/src/proactive/execution/repository.js +19 -2
- package/dist/src/proactive/execution/worker.js +14 -4
- package/dist/src/proactive/experience.d.ts +4 -1
- package/dist/src/proactive/experience.js +3 -0
- package/dist/src/proactive/follow-ups.d.ts +5 -0
- package/dist/src/proactive/follow-ups.js +18 -7
- package/dist/src/proactive/inbox/cards.js +2 -1
- package/dist/src/proactive/inbox/delivery.js +6 -7
- package/dist/src/proactive/inbox/digest.d.ts +1 -1
- package/dist/src/proactive/inbox/digest.js +23 -13
- package/dist/src/proactive/inbox/notification-policy.d.ts +1 -1
- package/dist/src/proactive/inbox/notification-policy.js +9 -6
- package/dist/src/proactive/inbox/repository.js +3 -2
- package/dist/src/proactive/inbox/service.d.ts +6 -0
- package/dist/src/proactive/inbox/service.js +18 -0
- package/dist/src/proactive/inbox/types.d.ts +1 -0
- package/dist/src/proactive/policy/presence.d.ts +1 -1
- package/dist/src/proactive/policy/presence.js +7 -5
- package/dist/src/proactive/policy/service.d.ts +8 -5
- package/dist/src/proactive/policy/service.js +12 -12
- package/dist/src/proactive/scenarios/control.d.ts +3 -3
- package/dist/src/proactive/scenarios/control.js +12 -2
- package/dist/src/proactive/source-freshness.d.ts +8 -0
- package/dist/src/proactive/source-freshness.js +27 -0
- package/dist/src/proactive/status.d.ts +2 -0
- package/dist/src/proactive/status.js +21 -0
- package/dist/src/proactive/temporal/worker.js +2 -1
- package/dist/src/realtime/runtime.js +31 -5
- package/dist/src/realtime/writer.js +16 -9
- package/dist/src/storage/sqlite/import-repository.d.ts +18 -0
- package/dist/src/storage/sqlite/import-repository.js +35 -0
- package/dist/src/storage/sqlite/import-selection-repository.d.ts +15 -0
- package/dist/src/storage/sqlite/import-selection-repository.js +28 -0
- package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/knowledge-repository.js +2 -2
- package/dist/src/storage/sqlite/migrations/174_capability_imports.sql +11 -0
- package/dist/src/storage/sqlite/migrations/175_import_selections.sql +8 -0
- package/dist/src/storage/sqlite/migrations/176_proactive_quality.sql +5 -0
- package/dist/src/storage/sqlite/migrations/177_proactive_check_controls.sql +25 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/work-discovery/candidate-discovery.js +1 -1
- package/dist/src/work-discovery/probe.js +1 -1
- package/package.json +4 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-SElFkQd6.js +0 -1
- package/dist/gateway/static/root/assets/agents-DYazUaZ6.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-BzrodN8C.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace--A4I0jMu.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-DDTXUNWK.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-Ll5UeXq5.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-BzL15bkU.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-RPw1AOMb.js +0 -2
- package/dist/gateway/static/root/assets/device-pairing-wizard-D0_tCX49.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-DOeeTdWE.js +0 -1
- package/dist/gateway/static/root/assets/home-page-Djw1H_Go.js +0 -1
- package/dist/gateway/static/root/assets/index-B_Sg5BKz.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-BPqgyYJq.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BHax3XlS.js +0 -2
- package/dist/gateway/static/root/assets/messages-DYFcjtmG.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-Cs46LFXO.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-BUkcn_0t.js +0 -8
- package/dist/gateway/static/root/assets/proactive-page-Bn484J9v.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-LcH21ixD.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-DelBiwyB.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-3BjFYXCf.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CVFirgVd.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DyfBpqkY.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CrXhTzHr.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-DyM_D8hM.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Bys58-15.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-sWNvFo6D.js +0 -2
- package/dist/gateway/static/root/assets/task-detail-page-B18NcZQJ.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-ul-zr58b.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-BY_AWs7S.js +0 -6
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { containsSecret } from "./secrets.js";
|
|
2
|
+
import { ImportError } from "./types.js";
|
|
3
|
+
import { IMPORT_LIMITS, digest, readRegularFile, readTree } from "./files.js";
|
|
4
|
+
import { inspectMcp, inspectSkill } from "./compatibility.js";
|
|
5
|
+
import { IMPORT_SOURCES, sourceLayout } from "./sources.js";
|
|
6
|
+
import { basename, join } from "node:path";
|
|
7
|
+
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { setImmediate } from "node:timers/promises";
|
|
10
|
+
import { parse as parse$1 } from "smol-toml";
|
|
11
|
+
//#region src/imports/scanner.ts
|
|
12
|
+
function scanResult(source) {
|
|
13
|
+
if (!IMPORT_SOURCES.some((s) => s.id === source)) throw new ImportError("unsupported_source", "Unsupported source");
|
|
14
|
+
return {
|
|
15
|
+
id: randomUUID(),
|
|
16
|
+
createdAt: Date.now(),
|
|
17
|
+
source,
|
|
18
|
+
candidates: [],
|
|
19
|
+
diagnostics: []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function base(source, scope, location, shared = false) {
|
|
23
|
+
return {
|
|
24
|
+
id: randomUUID(),
|
|
25
|
+
source,
|
|
26
|
+
scope,
|
|
27
|
+
location,
|
|
28
|
+
shared
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function appendMcp(scan, raw, scope, location) {
|
|
32
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
|
|
33
|
+
for (const [name, config] of Object.entries(raw)) scan.candidates.push(inspectMcp(base(scan.source, scope, location), name, config));
|
|
34
|
+
}
|
|
35
|
+
async function scanLocal(input) {
|
|
36
|
+
const scan = scanResult(input.source);
|
|
37
|
+
const { home, root, layout } = sourceLayout(input.source, input.home, input.root);
|
|
38
|
+
const scopes = (input.projectOnly ? [] : layout.skills).map((s) => ({
|
|
39
|
+
path: join(s.base === "home" ? home : root, s.path),
|
|
40
|
+
scope: "user",
|
|
41
|
+
shared: s.shared
|
|
42
|
+
}));
|
|
43
|
+
if (input.projectRoot) scopes.push({
|
|
44
|
+
path: join(input.projectRoot, layout.projectSkills),
|
|
45
|
+
scope: "project",
|
|
46
|
+
shared: layout.skills.some((s) => s.shared)
|
|
47
|
+
});
|
|
48
|
+
const seen = /* @__PURE__ */ new Set();
|
|
49
|
+
const budget = input.budget ?? {
|
|
50
|
+
bytes: 0,
|
|
51
|
+
files: 0
|
|
52
|
+
};
|
|
53
|
+
const consume = (bytes, files) => {
|
|
54
|
+
budget.bytes += bytes;
|
|
55
|
+
budget.files += files;
|
|
56
|
+
if (budget.bytes > IMPORT_LIMITS.total || budget.files > IMPORT_LIMITS.count) throw new ImportError("limit_exceeded", "Import exceeds batch limits", 413);
|
|
57
|
+
};
|
|
58
|
+
for (const scope of scopes) {
|
|
59
|
+
if (!existsSync(scope.path)) continue;
|
|
60
|
+
let entries;
|
|
61
|
+
try {
|
|
62
|
+
entries = readdirSync(scope.path, { withFileTypes: true });
|
|
63
|
+
} catch {
|
|
64
|
+
scan.diagnostics.push("Unable to read skills directory");
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
await setImmediate();
|
|
69
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
70
|
+
const location = join(scope.path, entry.name);
|
|
71
|
+
if (!existsSync(join(location, "SKILL.md"))) continue;
|
|
72
|
+
try {
|
|
73
|
+
const real = realpathSync(location);
|
|
74
|
+
if (seen.has(real)) continue;
|
|
75
|
+
seen.add(real);
|
|
76
|
+
const files = readTree(location);
|
|
77
|
+
consume(files.reduce((n, f) => n + Buffer.byteLength(f.data, "base64"), 0), files.length);
|
|
78
|
+
scan.candidates.push(inspectSkill(base(input.source, scope.scope, real, scope.shared), files));
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (error instanceof ImportError && error.code === "limit_exceeded") throw error;
|
|
81
|
+
scan.diagnostics.push(`${entry.name}: ${error instanceof ImportError ? error.message : "Unable to read skill"}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const configs = [{
|
|
86
|
+
path: join(root, layout.config.path),
|
|
87
|
+
scope: "user"
|
|
88
|
+
}];
|
|
89
|
+
if (input.projectRoot) configs.push({
|
|
90
|
+
path: join(input.projectRoot, layout.projectConfig),
|
|
91
|
+
scope: "project"
|
|
92
|
+
});
|
|
93
|
+
for (const config of configs) {
|
|
94
|
+
if (!existsSync(config.path)) continue;
|
|
95
|
+
try {
|
|
96
|
+
const text = readRegularFile(config.path, 1024 * 1024).toString("utf8");
|
|
97
|
+
const parsed = layout.config.format === "toml" ? parse$1(text) : JSON.parse(text);
|
|
98
|
+
if (!input.projectOnly || config.scope === "project") appendMcp(scan, parsed[layout.config.mcpKey], config.scope, config.path);
|
|
99
|
+
const projects = parsed.projects;
|
|
100
|
+
if (config.scope === "user" && projects && typeof projects === "object" && !Array.isArray(projects)) {
|
|
101
|
+
scan.projectRoots = Object.keys(projects);
|
|
102
|
+
if (input.projectRoot) {
|
|
103
|
+
const project = projects[input.projectRoot];
|
|
104
|
+
appendMcp(scan, project?.[layout.config.mcpKey], "project", config.path);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
scan.diagnostics.push(`${basename(config.path)}: invalid or unreadable configuration`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const addDocument = (path, scope) => {
|
|
112
|
+
if (!existsSync(path)) return;
|
|
113
|
+
try {
|
|
114
|
+
const content = readRegularFile(path, 128 * 1024).toString("utf8").trim();
|
|
115
|
+
if (!content) return;
|
|
116
|
+
consume(Buffer.byteLength(content), 1);
|
|
117
|
+
const blocked = containsSecret(content);
|
|
118
|
+
scan.candidates.push({
|
|
119
|
+
...base(input.source, scope, realpathSync(path)),
|
|
120
|
+
kind: "rule",
|
|
121
|
+
name: basename(path),
|
|
122
|
+
description: "",
|
|
123
|
+
hash: digest(content),
|
|
124
|
+
files: [],
|
|
125
|
+
compatibility: blocked ? "blocked" : "compatible",
|
|
126
|
+
findings: blocked ? ["Document contains probable credentials"] : [],
|
|
127
|
+
requiredEnv: [],
|
|
128
|
+
content: blocked ? void 0 : content
|
|
129
|
+
});
|
|
130
|
+
} catch {
|
|
131
|
+
scan.diagnostics.push(`${basename(path)}: unable to read context document`);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const addInstructions = (directory, groups, scope) => {
|
|
135
|
+
for (const names of groups) {
|
|
136
|
+
const path = names.map((name) => join(directory, name)).find(existsSync);
|
|
137
|
+
if (path) addDocument(path, scope);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const addRules = (directory, scope) => {
|
|
141
|
+
if (!existsSync(directory)) return;
|
|
142
|
+
try {
|
|
143
|
+
for (const entry of readdirSync(directory, { withFileTypes: true }).slice(0, 100)) if (entry.isFile() && entry.name.endsWith(".md")) addDocument(join(directory, entry.name), scope);
|
|
144
|
+
} catch {
|
|
145
|
+
scan.diagnostics.push("Unable to read rules directory");
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
if (!input.projectOnly) {
|
|
149
|
+
addInstructions(root, layout.instructions, "user");
|
|
150
|
+
if (layout.rules) addRules(join(root, layout.rules), "user");
|
|
151
|
+
}
|
|
152
|
+
if (input.projectRoot) {
|
|
153
|
+
addInstructions(input.projectRoot, layout.projectInstructions, "project");
|
|
154
|
+
if (layout.projectRules) addRules(join(input.projectRoot, layout.projectRules), "project");
|
|
155
|
+
}
|
|
156
|
+
return scan;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { IMPORT_SOURCES, scanLocal };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/imports/secrets.ts
|
|
2
|
+
function containsSecret(text) {
|
|
3
|
+
return /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|\b(?:sk-[a-zA-Z0-9_-]{20,}|gh[pousr]_[a-zA-Z0-9]{20,}|AKIA[A-Z0-9]{16})\b/i.test(text) || /(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|authorization)\s*[=:]\s*["']?(?!\$|<|\{|process\.env|os\.environ)[a-zA-Z0-9_+/.-]{12,}/i.test(text);
|
|
4
|
+
}
|
|
5
|
+
function isCredentialPath(path) {
|
|
6
|
+
return /(^|\/)(\.env(?:\..*)?|auth\.json|credentials[^/]*|id_rsa|id_ed25519)$/i.test(path);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { containsSecret, isCredentialPath };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ImportSource } from './types.js';
|
|
2
|
+
interface SourceLayout {
|
|
3
|
+
id: ImportSource;
|
|
4
|
+
name: string;
|
|
5
|
+
directory: string;
|
|
6
|
+
environment: string;
|
|
7
|
+
skills: Array<{
|
|
8
|
+
base: 'home' | 'root';
|
|
9
|
+
path: string;
|
|
10
|
+
shared: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
projectSkills: string;
|
|
13
|
+
instructions: string[][];
|
|
14
|
+
projectInstructions: string[][];
|
|
15
|
+
rules?: string;
|
|
16
|
+
projectRules?: string;
|
|
17
|
+
config: {
|
|
18
|
+
path: string;
|
|
19
|
+
format: 'json' | 'toml';
|
|
20
|
+
mcpKey: string;
|
|
21
|
+
};
|
|
22
|
+
projectConfig: string;
|
|
23
|
+
}
|
|
24
|
+
/** Product differences live here; readers and destination writers are shared. */
|
|
25
|
+
export declare const IMPORT_SOURCES: readonly SourceLayout[];
|
|
26
|
+
export declare function sourceLayout(source: ImportSource, home?: string, root?: string): {
|
|
27
|
+
layout: SourceLayout;
|
|
28
|
+
home: string;
|
|
29
|
+
root: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function detectImportSources(): {
|
|
32
|
+
id: ImportSource;
|
|
33
|
+
name: string;
|
|
34
|
+
detected: boolean;
|
|
35
|
+
}[];
|
|
36
|
+
export declare function isImportSource(value: string): value is ImportSource;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ImportError } from "./types.js";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
//#region src/imports/sources.ts
|
|
6
|
+
/** Product differences live here; readers and destination writers are shared. */
|
|
7
|
+
const IMPORT_SOURCES = [{
|
|
8
|
+
id: "codex",
|
|
9
|
+
name: "Codex",
|
|
10
|
+
directory: ".codex",
|
|
11
|
+
environment: "CODEX_HOME",
|
|
12
|
+
skills: [{
|
|
13
|
+
base: "home",
|
|
14
|
+
path: ".agents/skills",
|
|
15
|
+
shared: true
|
|
16
|
+
}],
|
|
17
|
+
projectSkills: ".agents/skills",
|
|
18
|
+
instructions: [["AGENTS.override.md", "AGENTS.md"]],
|
|
19
|
+
projectInstructions: [["AGENTS.override.md", "AGENTS.md"]],
|
|
20
|
+
config: {
|
|
21
|
+
path: "config.toml",
|
|
22
|
+
format: "toml",
|
|
23
|
+
mcpKey: "mcp_servers"
|
|
24
|
+
},
|
|
25
|
+
projectConfig: ".codex/config.toml"
|
|
26
|
+
}, {
|
|
27
|
+
id: "claude-code",
|
|
28
|
+
name: "Claude Code",
|
|
29
|
+
directory: ".claude",
|
|
30
|
+
environment: "CLAUDE_CONFIG_DIR",
|
|
31
|
+
skills: [{
|
|
32
|
+
base: "root",
|
|
33
|
+
path: "skills",
|
|
34
|
+
shared: false
|
|
35
|
+
}],
|
|
36
|
+
projectSkills: ".claude/skills",
|
|
37
|
+
instructions: [["CLAUDE.md"]],
|
|
38
|
+
projectInstructions: [
|
|
39
|
+
["CLAUDE.md"],
|
|
40
|
+
[".claude/CLAUDE.md"],
|
|
41
|
+
["CLAUDE.local.md"]
|
|
42
|
+
],
|
|
43
|
+
rules: "rules",
|
|
44
|
+
projectRules: ".claude/rules",
|
|
45
|
+
config: {
|
|
46
|
+
path: "../.claude.json",
|
|
47
|
+
format: "json",
|
|
48
|
+
mcpKey: "mcpServers"
|
|
49
|
+
},
|
|
50
|
+
projectConfig: ".mcp.json"
|
|
51
|
+
}];
|
|
52
|
+
function sourceLayout(source, home, root) {
|
|
53
|
+
const layout = IMPORT_SOURCES.find((s) => s.id === source);
|
|
54
|
+
if (!layout) throw new ImportError("unsupported_source", "Unsupported source");
|
|
55
|
+
return {
|
|
56
|
+
layout,
|
|
57
|
+
home: home ?? homedir(),
|
|
58
|
+
root: root ?? (home ? void 0 : process.env[layout.environment]) ?? join(home ?? homedir(), layout.directory)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function detectImportSources() {
|
|
62
|
+
return IMPORT_SOURCES.map((s) => {
|
|
63
|
+
const { root } = sourceLayout(s.id);
|
|
64
|
+
return {
|
|
65
|
+
id: s.id,
|
|
66
|
+
name: s.name,
|
|
67
|
+
detected: existsSync(root) || existsSync(join(root, s.config.path))
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function isImportSource(value) {
|
|
72
|
+
return IMPORT_SOURCES.some((source) => source.id === value);
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { IMPORT_SOURCES, detectImportSources, isImportSource, sourceLayout };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export type ImportSource = 'codex' | 'claude-code';
|
|
2
|
+
export type ImportScope = 'user' | 'project';
|
|
3
|
+
export type Compatibility = 'compatible' | 'needs_setup' | 'blocked' | 'unsupported';
|
|
4
|
+
export interface ImportFile {
|
|
5
|
+
path: string;
|
|
6
|
+
data: string;
|
|
7
|
+
executable: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ImportCandidate {
|
|
10
|
+
id: string;
|
|
11
|
+
source: ImportSource;
|
|
12
|
+
kind: 'skill' | 'mcp' | 'rule';
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
scope: ImportScope;
|
|
16
|
+
location: string;
|
|
17
|
+
hash: string;
|
|
18
|
+
compatibility: Compatibility;
|
|
19
|
+
findings: string[];
|
|
20
|
+
files: ImportFile[];
|
|
21
|
+
content?: string;
|
|
22
|
+
mcp?: Record<string, unknown>;
|
|
23
|
+
requiredEnv: string[];
|
|
24
|
+
shared: boolean;
|
|
25
|
+
connected?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface ImportScan {
|
|
28
|
+
id: string;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
source: ImportSource;
|
|
31
|
+
candidates: ImportCandidate[];
|
|
32
|
+
diagnostics: string[];
|
|
33
|
+
projectRoots?: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface ImportTarget {
|
|
36
|
+
projectId?: string;
|
|
37
|
+
root: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ImportAction {
|
|
40
|
+
candidateId: string;
|
|
41
|
+
operation: 'skip' | 'create' | 'rename' | 'replace';
|
|
42
|
+
name: string;
|
|
43
|
+
beforeHash: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface ImportPlan {
|
|
46
|
+
id: string;
|
|
47
|
+
scanId: string;
|
|
48
|
+
createdAt: number;
|
|
49
|
+
expiresAt: number;
|
|
50
|
+
target: ImportTarget;
|
|
51
|
+
targetRevision: string;
|
|
52
|
+
actions: ImportAction[];
|
|
53
|
+
}
|
|
54
|
+
export interface ImportJobItem {
|
|
55
|
+
action: ImportAction;
|
|
56
|
+
status: 'staged' | 'skipped' | 'publishing' | 'active' | 'rolling_back' | 'rolled_back' | 'failed';
|
|
57
|
+
error?: string;
|
|
58
|
+
afterHash?: string;
|
|
59
|
+
backupPath?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ImportJob {
|
|
62
|
+
id: string;
|
|
63
|
+
plan: ImportPlan;
|
|
64
|
+
createdAt: number;
|
|
65
|
+
expiresAt: number;
|
|
66
|
+
items: ImportJobItem[];
|
|
67
|
+
}
|
|
68
|
+
export declare class ImportError extends Error {
|
|
69
|
+
readonly code: string;
|
|
70
|
+
readonly status: 400 | 403 | 404 | 409 | 413;
|
|
71
|
+
constructor(code: string, message: string, status?: 400 | 403 | 404 | 409 | 413);
|
|
72
|
+
}
|
|
73
|
+
export type InventoryStatus = 'ready' | 'existing' | 'conflict' | 'blocked';
|
|
74
|
+
export interface InventoryItem {
|
|
75
|
+
id: string;
|
|
76
|
+
kind: 'skill' | 'context' | 'project';
|
|
77
|
+
parentId?: string;
|
|
78
|
+
name: string;
|
|
79
|
+
description: string;
|
|
80
|
+
displayPath: string;
|
|
81
|
+
scope: ImportScope;
|
|
82
|
+
status: InventoryStatus;
|
|
83
|
+
reason?: string;
|
|
84
|
+
suggested: boolean;
|
|
85
|
+
targetName?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface ImportInventory {
|
|
88
|
+
id: string;
|
|
89
|
+
source: ImportSource;
|
|
90
|
+
createdAt: number;
|
|
91
|
+
expiresAt: number;
|
|
92
|
+
candidates: InventoryItem[];
|
|
93
|
+
notices: string[];
|
|
94
|
+
complete: boolean;
|
|
95
|
+
}
|
|
96
|
+
export interface StoredInventoryItem extends InventoryItem {
|
|
97
|
+
location: string;
|
|
98
|
+
scanId?: string;
|
|
99
|
+
candidate?: ImportCandidate;
|
|
100
|
+
targetRoot?: string;
|
|
101
|
+
projectId?: string;
|
|
102
|
+
}
|
|
103
|
+
export interface StoredInventory extends Omit<ImportInventory, 'candidates'> {
|
|
104
|
+
candidates: StoredInventoryItem[];
|
|
105
|
+
scanIds: string[];
|
|
106
|
+
}
|
|
107
|
+
export interface ImportSelection {
|
|
108
|
+
inventoryId: string;
|
|
109
|
+
candidateIds: string[];
|
|
110
|
+
requestId: string;
|
|
111
|
+
retryOf?: string;
|
|
112
|
+
}
|
|
113
|
+
export interface ImportRunItem {
|
|
114
|
+
candidateId: string;
|
|
115
|
+
kind: InventoryItem['kind'];
|
|
116
|
+
name: string;
|
|
117
|
+
status: 'pending' | 'imported' | 'existing' | 'failed';
|
|
118
|
+
targetId?: string;
|
|
119
|
+
jobId?: string;
|
|
120
|
+
error?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface ProductImportResult {
|
|
123
|
+
id: string;
|
|
124
|
+
source: ImportSource;
|
|
125
|
+
createdAt: number;
|
|
126
|
+
inventoryId: string;
|
|
127
|
+
selectionHash: string;
|
|
128
|
+
status: 'running' | 'completed' | 'partial';
|
|
129
|
+
items: ImportRunItem[];
|
|
130
|
+
skills: number;
|
|
131
|
+
context: number;
|
|
132
|
+
projects: number;
|
|
133
|
+
skipped: number;
|
|
134
|
+
issues: Array<{
|
|
135
|
+
name: string;
|
|
136
|
+
reason: string;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
export interface DetectedImportSource {
|
|
140
|
+
id: ImportSource;
|
|
141
|
+
name: string;
|
|
142
|
+
detected: boolean;
|
|
143
|
+
lastImport?: ProductImportResult;
|
|
144
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/imports/types.ts
|
|
2
|
+
var ImportError = class extends Error {
|
|
3
|
+
constructor(code, message, status = 400) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.name = "ImportError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { ImportError };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/infra/background-task.ts
|
|
2
|
+
/** Run one background tick at a time, reporting once per consecutive failure period. */
|
|
3
|
+
function createBackgroundTask(run, onError) {
|
|
4
|
+
let running = false;
|
|
5
|
+
let failed = false;
|
|
6
|
+
return () => {
|
|
7
|
+
if (running) return;
|
|
8
|
+
running = true;
|
|
9
|
+
(async () => {
|
|
10
|
+
try {
|
|
11
|
+
await run();
|
|
12
|
+
failed = false;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
if (!failed) {
|
|
15
|
+
failed = true;
|
|
16
|
+
onError(error);
|
|
17
|
+
}
|
|
18
|
+
} finally {
|
|
19
|
+
running = false;
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { createBackgroundTask };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function recordProcessDiagnostic(event: string, detail: unknown): void;
|
|
2
|
+
/** Independent of SQLite and async logger transports; safe to use during process failure. */
|
|
3
|
+
export declare function createProcessDiagnosticWriter(path: string): (event: string, detail: unknown) => void;
|
|
4
|
+
/** Observe fatal exceptions without resuming execution in an unknown process state. */
|
|
5
|
+
export declare function installProcessDiagnostics(path: string): () => void;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { init_redact, redactObject, redactSensitiveInfo } from "../utils/logger/redact.js";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { appendFileSync, mkdirSync, renameSync, rmSync, statSync } from "node:fs";
|
|
4
|
+
import { inspect } from "node:util";
|
|
5
|
+
//#region src/infra/process-diagnostics.ts
|
|
6
|
+
init_redact();
|
|
7
|
+
const MAX_LOG_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
const MAX_DETAIL_CHARS = 64 * 1024;
|
|
9
|
+
function diagnosticValue(value, depth = 0) {
|
|
10
|
+
if (depth > 5) return "[MaxDepth]";
|
|
11
|
+
if (value instanceof Error) return {
|
|
12
|
+
name: value.name,
|
|
13
|
+
message: value.message,
|
|
14
|
+
stack: value.stack,
|
|
15
|
+
...value.cause === void 0 ? {} : { cause: diagnosticValue(value.cause, depth + 1) }
|
|
16
|
+
};
|
|
17
|
+
if (Array.isArray(value)) return value.slice(0, 30).map((item) => diagnosticValue(item, depth + 1));
|
|
18
|
+
if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).slice(0, 30).map(([key, item]) => [key, diagnosticValue(item, depth + 1)]));
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
let activeWriter;
|
|
22
|
+
function recordProcessDiagnostic(event, detail) {
|
|
23
|
+
activeWriter?.(event, detail);
|
|
24
|
+
}
|
|
25
|
+
/** Independent of SQLite and async logger transports; safe to use during process failure. */
|
|
26
|
+
function createProcessDiagnosticWriter(path) {
|
|
27
|
+
return (event, detail) => {
|
|
28
|
+
try {
|
|
29
|
+
const text = typeof detail === "string" ? detail : inspect(redactObject(diagnosticValue(detail)), {
|
|
30
|
+
depth: 5,
|
|
31
|
+
maxArrayLength: 30,
|
|
32
|
+
maxStringLength: MAX_DETAIL_CHARS,
|
|
33
|
+
customInspect: false,
|
|
34
|
+
getters: false
|
|
35
|
+
});
|
|
36
|
+
const line = JSON.stringify({
|
|
37
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38
|
+
pid: process.pid,
|
|
39
|
+
event,
|
|
40
|
+
detail: redactSensitiveInfo(text).slice(-MAX_DETAIL_CHARS)
|
|
41
|
+
}) + "\n";
|
|
42
|
+
mkdirSync(dirname(path), {
|
|
43
|
+
recursive: true,
|
|
44
|
+
mode: 448
|
|
45
|
+
});
|
|
46
|
+
let size = 0;
|
|
47
|
+
try {
|
|
48
|
+
size = statSync(path).size;
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (err.code !== "ENOENT") throw err;
|
|
51
|
+
}
|
|
52
|
+
if (size + Buffer.byteLength(line) > MAX_LOG_BYTES) {
|
|
53
|
+
rmSync(`${path}.2`, { force: true });
|
|
54
|
+
try {
|
|
55
|
+
renameSync(`${path}.1`, `${path}.2`);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
if (err.code !== "ENOENT") throw err;
|
|
58
|
+
}
|
|
59
|
+
renameSync(path, `${path}.1`);
|
|
60
|
+
}
|
|
61
|
+
appendFileSync(path, line, {
|
|
62
|
+
encoding: "utf8",
|
|
63
|
+
mode: 384
|
|
64
|
+
});
|
|
65
|
+
} catch {}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Observe fatal exceptions without resuming execution in an unknown process state. */
|
|
69
|
+
function installProcessDiagnostics(path) {
|
|
70
|
+
const write = createProcessDiagnosticWriter(path);
|
|
71
|
+
const previousWriter = activeWriter;
|
|
72
|
+
activeWriter = write;
|
|
73
|
+
const onFatal = (error, origin) => write("uncaught_exception", {
|
|
74
|
+
origin,
|
|
75
|
+
error,
|
|
76
|
+
uptimeSeconds: process.uptime(),
|
|
77
|
+
memory: process.memoryUsage()
|
|
78
|
+
});
|
|
79
|
+
const onExit = (code) => write("process_exit", {
|
|
80
|
+
code,
|
|
81
|
+
uptimeSeconds: process.uptime()
|
|
82
|
+
});
|
|
83
|
+
process.on("uncaughtExceptionMonitor", onFatal);
|
|
84
|
+
process.on("exit", onExit);
|
|
85
|
+
write("process_start", {
|
|
86
|
+
node: process.version,
|
|
87
|
+
platform: process.platform,
|
|
88
|
+
arch: process.arch
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
if (activeWriter === write) activeWriter = previousWriter;
|
|
92
|
+
process.removeListener("uncaughtExceptionMonitor", onFatal);
|
|
93
|
+
process.removeListener("exit", onExit);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { createProcessDiagnosticWriter, installProcessDiagnostics, recordProcessDiagnostic };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
3
|
import { resolveGlobalSingleton } from "../utils/global-singleton.js";
|
|
4
|
+
import { recordProcessDiagnostic } from "./process-diagnostics.js";
|
|
4
5
|
import { isTransientSqliteError } from "./sqlite-errors.js";
|
|
5
6
|
//#region src/infra/unhandled-rejections.ts
|
|
6
7
|
init_logger();
|
|
@@ -10,12 +11,14 @@ function installSqliteTransientRejectionHandler() {
|
|
|
10
11
|
const state = resolveGlobalSingleton(installStateKey, () => ({ installed: false }));
|
|
11
12
|
if (state.installed) return;
|
|
12
13
|
process.on("unhandledRejection", (reason) => {
|
|
13
|
-
|
|
14
|
+
recordProcessDiagnostic("unhandled_rejection", reason);
|
|
14
15
|
const em = reason instanceof Error ? reason.message : String(reason);
|
|
15
|
-
|
|
16
|
+
const fields = {
|
|
16
17
|
err: reason instanceof Error ? reason : void 0,
|
|
17
18
|
errorMessage: em
|
|
18
|
-
}
|
|
19
|
+
};
|
|
20
|
+
if (isTransientSqliteError(reason)) log.warn(fields, `Transient SQLite rejection: ${em}`);
|
|
21
|
+
else log.error(fields, `Unhandled promise rejection: ${em}`);
|
|
19
22
|
});
|
|
20
23
|
state.installed = true;
|
|
21
24
|
}
|
|
@@ -3,9 +3,9 @@ import { init_logger } from "../utils/logger.js";
|
|
|
3
3
|
import { init_paths, resolveConfigPath } from "../config/paths.js";
|
|
4
4
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
5
|
import { isRestartEnabled } from "../config/commands.flags.js";
|
|
6
|
-
import { resolveGatewayService } from "../daemon/service.js";
|
|
7
6
|
import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "./restart.js";
|
|
8
7
|
import { findVerifiedGatewayListenerPidsOnPortSync, signalVerifiedGatewayPidSync } from "./gateway-processes.js";
|
|
8
|
+
import { resolveGatewayService } from "../daemon/service.js";
|
|
9
9
|
import { refreshGatewayServiceAfterUpdate } from "./update-service-refresh.js";
|
|
10
10
|
//#region src/infra/update-restart.ts
|
|
11
11
|
init_loader();
|
|
@@ -89,6 +89,7 @@ var KnowledgeIngestionService = class {
|
|
|
89
89
|
const cursorBefore = this.state.getCursor(params.instanceId, params.collectionScope);
|
|
90
90
|
const run = startKnowledgeSyncRun({
|
|
91
91
|
sourceInstanceId: params.instanceId,
|
|
92
|
+
collectionScope: params.collectionScope,
|
|
92
93
|
cursorBefore
|
|
93
94
|
});
|
|
94
95
|
const controller = params.signal ? null : new AbortController();
|
|
@@ -142,7 +142,9 @@ function searchKnowledgeItems(input) {
|
|
|
142
142
|
const visible = visibilityClause(input.context);
|
|
143
143
|
const sourceParts = [];
|
|
144
144
|
const sourceValues = [];
|
|
145
|
-
|
|
145
|
+
const importedSource = "COALESCE(json_extract(k.source_json, '$.kind'), '') = 'product_import'";
|
|
146
|
+
if (input.sources?.includes("connector")) sourceParts.push(`(k.record_class = 'source_index' AND NOT (${importedSource}))`);
|
|
147
|
+
if (input.sources?.includes("workspace")) sourceParts.push(`(k.record_class = 'source_index' AND ${importedSource})`);
|
|
146
148
|
const memoryScopes = input.sources?.filter((source) => source !== "connector") ?? [];
|
|
147
149
|
if (memoryScopes.length) {
|
|
148
150
|
sourceParts.push(`(k.record_class = 'memory' AND k.scope_type IN (${memoryScopes.map(() => "?").join(", ")}))`);
|
|
@@ -163,7 +165,7 @@ function searchKnowledgeItems(input) {
|
|
|
163
165
|
ORDER BY rank ASC, k.importance DESC, k.updated_at DESC LIMIT ?`).all(fts, principalId, asOf, asOf, asOf, ...input.recordClass ? [input.recordClass] : [], ...sourceValues, ...visible.values, limit).map(fromRow);
|
|
164
166
|
}
|
|
165
167
|
function knowledgeSourceAllowed(item, sources) {
|
|
166
|
-
if (item.recordClass === "source_index") return sources.includes("connector");
|
|
168
|
+
if (item.recordClass === "source_index") return sources.includes(item.source.kind === "product_import" ? "workspace" : "connector");
|
|
167
169
|
return item.scope.type === "session" ? sources.includes("session") : item.scope.type === "workspace" ? sources.includes("workspace") : item.scope.type === "project" ? sources.includes("project") : false;
|
|
168
170
|
}
|
|
169
171
|
//#endregion
|