@useorgx/wizard 0.1.52 → 0.1.56
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 +11 -5
- package/dist/cli.js +996 -189
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="02842523-d681-5cea-96aa-0f0c896e9fb5")}catch(e){}}();
|
|
6
6
|
import * as clack from "@clack/prompts";
|
|
7
|
-
import { spawnSync as
|
|
7
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
8
8
|
import { readFileSync as readFileSync8 } from "fs";
|
|
9
9
|
import { hostname } from "os";
|
|
10
10
|
import { resolve as resolve3 } from "path";
|
|
@@ -82,6 +82,7 @@ var CLAUDE_DIR = join(HOME, ".claude");
|
|
|
82
82
|
var CURSOR_DIR = join(HOME, ".cursor");
|
|
83
83
|
var CODEX_DIR = join(HOME, ".codex");
|
|
84
84
|
var OPENCLAW_DIR = join(HOME, ".openclaw");
|
|
85
|
+
var DEEPSEEK_HARNESS_DIR = process.env.DSH_HOME?.trim() || join(HOME, ".dsh");
|
|
85
86
|
var AGENTS_DIR = join(HOME, ".agents");
|
|
86
87
|
var CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, "projects");
|
|
87
88
|
var CODEX_SESSIONS_DIR = join(CODEX_DIR, "sessions");
|
|
@@ -125,6 +126,15 @@ var CLAUDE_INSTALL_PATHS = uniquePaths([CLAUDE_DIR]);
|
|
|
125
126
|
var CURSOR_INSTALL_PATHS = uniquePaths([CURSOR_DIR]);
|
|
126
127
|
var CODEX_INSTALL_PATHS = uniquePaths([CODEX_DIR]);
|
|
127
128
|
var OPENCLAW_INSTALL_PATHS = uniquePaths([OPENCLAW_DIR]);
|
|
129
|
+
var DEEPSEEK_HARNESS_PROFILE_PATH = join(
|
|
130
|
+
DEEPSEEK_HARNESS_DIR,
|
|
131
|
+
"profiles",
|
|
132
|
+
"headless",
|
|
133
|
+
"package.json"
|
|
134
|
+
);
|
|
135
|
+
var DEEPSEEK_HARNESS_INSTALL_PATHS = uniquePaths([
|
|
136
|
+
DEEPSEEK_HARNESS_DIR
|
|
137
|
+
]);
|
|
128
138
|
var VSCODE_MCP_PATHS = uniquePaths([
|
|
129
139
|
join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
|
|
130
140
|
join(XDG_CONFIG_HOME, "Code", "User", "mcp.json"),
|
|
@@ -1098,6 +1108,34 @@ async function exchangeCodeForTokens(options) {
|
|
|
1098
1108
|
...typeof data.scope === "string" ? { scope: data.scope } : {}
|
|
1099
1109
|
};
|
|
1100
1110
|
}
|
|
1111
|
+
async function refreshAccessToken(options) {
|
|
1112
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
1113
|
+
const body = new URLSearchParams({
|
|
1114
|
+
grant_type: "refresh_token",
|
|
1115
|
+
refresh_token: options.refreshToken,
|
|
1116
|
+
client_id: options.clientId
|
|
1117
|
+
});
|
|
1118
|
+
const response = await fetchImpl(ORGX_HOSTED_OAUTH_TOKEN_URL, {
|
|
1119
|
+
method: "POST",
|
|
1120
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1121
|
+
body: body.toString(),
|
|
1122
|
+
signal: AbortSignal.timeout(1e4)
|
|
1123
|
+
});
|
|
1124
|
+
if (!response.ok) {
|
|
1125
|
+
const text2 = await response.text().catch(() => "");
|
|
1126
|
+
throw new Error(`Token refresh failed (HTTP ${response.status}): ${text2}`);
|
|
1127
|
+
}
|
|
1128
|
+
const data = await response.json();
|
|
1129
|
+
if (!isRecord(data) || typeof data.access_token !== "string") {
|
|
1130
|
+
throw new Error("Refresh response missing access_token.");
|
|
1131
|
+
}
|
|
1132
|
+
return {
|
|
1133
|
+
access_token: data.access_token,
|
|
1134
|
+
token_type: typeof data.token_type === "string" ? data.token_type : "Bearer",
|
|
1135
|
+
...typeof data.expires_in === "number" ? { expires_in: data.expires_in } : {},
|
|
1136
|
+
...typeof data.refresh_token === "string" ? { refresh_token: data.refresh_token } : {}
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1101
1139
|
async function startPkceLogin(options = {}) {
|
|
1102
1140
|
const port = options.preferredPort ?? ORGX_WIZARD_OAUTH_PREFERRED_PORT;
|
|
1103
1141
|
const scope = options.scope ?? ORGX_WIZARD_OAUTH_SCOPE;
|
|
@@ -1152,6 +1190,7 @@ var SURFACE_NAMES = [
|
|
|
1152
1190
|
"claude",
|
|
1153
1191
|
"cursor",
|
|
1154
1192
|
"codex",
|
|
1193
|
+
"deepseek",
|
|
1155
1194
|
"openclaw",
|
|
1156
1195
|
"vscode",
|
|
1157
1196
|
"windsurf",
|
|
@@ -1162,6 +1201,7 @@ var AUTOMATED_SURFACE_NAMES = [
|
|
|
1162
1201
|
"claude",
|
|
1163
1202
|
"cursor",
|
|
1164
1203
|
"codex",
|
|
1204
|
+
"deepseek",
|
|
1165
1205
|
"openclaw",
|
|
1166
1206
|
"vscode",
|
|
1167
1207
|
"windsurf",
|
|
@@ -2125,16 +2165,13 @@ async function checkWorkspaceConnectivity(options = {}) {
|
|
|
2125
2165
|
import { spawn } from "child_process";
|
|
2126
2166
|
import {
|
|
2127
2167
|
existsSync as existsSync4,
|
|
2128
|
-
mkdirSync as
|
|
2129
|
-
mkdtempSync,
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
rmSync,
|
|
2133
|
-
statSync as statSync2,
|
|
2134
|
-
writeFileSync as writeFileSync2
|
|
2168
|
+
mkdirSync as mkdirSync3,
|
|
2169
|
+
mkdtempSync as mkdtempSync2,
|
|
2170
|
+
rmSync as rmSync2,
|
|
2171
|
+
writeFileSync as writeFileSync3
|
|
2135
2172
|
} from "fs";
|
|
2136
2173
|
import { tmpdir } from "os";
|
|
2137
|
-
import { dirname as
|
|
2174
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
2138
2175
|
|
|
2139
2176
|
// src/surfaces/mcp-config.ts
|
|
2140
2177
|
import * as TOML from "@iarna/toml";
|
|
@@ -2481,6 +2518,10 @@ var SURFACE_LOCATORS = {
|
|
|
2481
2518
|
configPaths: CODEX_CONFIG_PATHS,
|
|
2482
2519
|
installPaths: CODEX_INSTALL_PATHS
|
|
2483
2520
|
},
|
|
2521
|
+
deepseek: {
|
|
2522
|
+
configPaths: [DEEPSEEK_HARNESS_PROFILE_PATH],
|
|
2523
|
+
installPaths: DEEPSEEK_HARNESS_INSTALL_PATHS
|
|
2524
|
+
},
|
|
2484
2525
|
openclaw: {
|
|
2485
2526
|
configPaths: OPENCLAW_CONFIG_PATHS,
|
|
2486
2527
|
installPaths: OPENCLAW_INSTALL_PATHS
|
|
@@ -2544,10 +2585,359 @@ function detectSurface(name, exists = existsSync2) {
|
|
|
2544
2585
|
return detection;
|
|
2545
2586
|
}
|
|
2546
2587
|
|
|
2588
|
+
// src/lib/claude-plugin-bundle.ts
|
|
2589
|
+
var ORGX_CLAUDE_PLUGIN_NAME = "orgx-claude-code-plugin";
|
|
2590
|
+
var ORGX_CLAUDE_MARKETPLACE_NAME = "orgx-local";
|
|
2591
|
+
var ORGX_CLAUDE_PLUGIN_VERSION = "0.1.12";
|
|
2592
|
+
var ORGX_CLAUDE_PLUGIN_REF = `v${ORGX_CLAUDE_PLUGIN_VERSION}`;
|
|
2593
|
+
var ORGX_CLAUDE_PLUGIN_MCP_URL = "https://mcp.useorgx.com/mcp?profile=claude-directory";
|
|
2594
|
+
var ALLOWED_FILES = [
|
|
2595
|
+
".claude-plugin/marketplace.json",
|
|
2596
|
+
".claude-plugin/plugin.json",
|
|
2597
|
+
".mcp.json",
|
|
2598
|
+
"commands/orgx-login.md",
|
|
2599
|
+
"commands/orgx-operator-chronicle.md",
|
|
2600
|
+
"commands/orgx-status.md",
|
|
2601
|
+
"skills/orgx-setup/SKILL.md"
|
|
2602
|
+
];
|
|
2603
|
+
var PROHIBITED_CONTENT = [
|
|
2604
|
+
{ label: "transcript access", pattern: /\btranscripts?\b/i },
|
|
2605
|
+
{
|
|
2606
|
+
label: "telemetry collection",
|
|
2607
|
+
pattern: /\b(?:collect|capture|record|send|upload|emit|track|enable|configure)\b[^\n]{0,80}\btelemetry\b/i
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
label: "telemetry collection",
|
|
2611
|
+
pattern: /\btelemetry\b[^\n]{0,40}\b(?:collection|capture|recording|upload|emission|tracking|enabled)\b/i
|
|
2612
|
+
},
|
|
2613
|
+
{
|
|
2614
|
+
label: "telemetry collection",
|
|
2615
|
+
pattern: /\btelemetry\b\s*[:=]\s*true\b/i
|
|
2616
|
+
},
|
|
2617
|
+
{ label: "dynamic context sync", pattern: /dynamic(?:[\s_-]+context)?[\s_-]+sync/i },
|
|
2618
|
+
{ label: "runtime hook", pattern: /orgx-session-hook|emit-execution-graph|post-install\.sh/i }
|
|
2619
|
+
];
|
|
2620
|
+
var MANIFEST_CAPABILITY_FIELDS = [
|
|
2621
|
+
"agents",
|
|
2622
|
+
"commands",
|
|
2623
|
+
"hooks",
|
|
2624
|
+
"lspServers",
|
|
2625
|
+
"mcpServers",
|
|
2626
|
+
"skills"
|
|
2627
|
+
];
|
|
2628
|
+
var EXPECTED_PLUGIN_MANIFEST = {
|
|
2629
|
+
$schema: "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
2630
|
+
name: ORGX_CLAUDE_PLUGIN_NAME,
|
|
2631
|
+
displayName: "OrgX",
|
|
2632
|
+
version: ORGX_CLAUDE_PLUGIN_VERSION,
|
|
2633
|
+
description: "Connect Claude Code to a focused, non-destructive, closed-world OrgX status profile through native OAuth.",
|
|
2634
|
+
author: {
|
|
2635
|
+
name: "OrgX Team",
|
|
2636
|
+
email: "reviewers@useorgx.com",
|
|
2637
|
+
url: "https://useorgx.com"
|
|
2638
|
+
},
|
|
2639
|
+
homepage: "https://useorgx.com",
|
|
2640
|
+
repository: "https://github.com/useorgx/orgx-claude-code-plugin",
|
|
2641
|
+
license: "MIT",
|
|
2642
|
+
keywords: [
|
|
2643
|
+
"orgx",
|
|
2644
|
+
"mcp",
|
|
2645
|
+
"productivity",
|
|
2646
|
+
"status",
|
|
2647
|
+
"native-oauth"
|
|
2648
|
+
]
|
|
2649
|
+
};
|
|
2650
|
+
function parseJsonFile(files, path) {
|
|
2651
|
+
const bytes = files.get(path);
|
|
2652
|
+
if (!bytes) {
|
|
2653
|
+
throw new Error(`Rejected Claude plugin bundle: required file '${path}' is missing.`);
|
|
2654
|
+
}
|
|
2655
|
+
let value;
|
|
2656
|
+
try {
|
|
2657
|
+
value = JSON.parse(bytes.toString("utf8"));
|
|
2658
|
+
} catch {
|
|
2659
|
+
throw new Error(`Rejected Claude plugin bundle: '${path}' is not valid JSON.`);
|
|
2660
|
+
}
|
|
2661
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2662
|
+
throw new Error(`Rejected Claude plugin bundle: '${path}' must contain a JSON object.`);
|
|
2663
|
+
}
|
|
2664
|
+
return value;
|
|
2665
|
+
}
|
|
2666
|
+
function assertExactKeys(value, expected, label) {
|
|
2667
|
+
const actualKeys = Object.keys(value).sort();
|
|
2668
|
+
const expectedKeys = [...expected].sort();
|
|
2669
|
+
if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {
|
|
2670
|
+
throw new Error(
|
|
2671
|
+
`Rejected Claude plugin bundle: ${label} must contain only ${expectedKeys.join(", ")}.`
|
|
2672
|
+
);
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
function canonicalizeJson(value) {
|
|
2676
|
+
if (Array.isArray(value)) {
|
|
2677
|
+
return `[${value.map((item) => canonicalizeJson(item)).join(",")}]`;
|
|
2678
|
+
}
|
|
2679
|
+
if (value && typeof value === "object") {
|
|
2680
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
2681
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalizeJson(item)}`).join(",")}}`;
|
|
2682
|
+
}
|
|
2683
|
+
return JSON.stringify(value) ?? "undefined";
|
|
2684
|
+
}
|
|
2685
|
+
function validateClaudePluginBundle(files) {
|
|
2686
|
+
const actualFiles = [...files.keys()].sort();
|
|
2687
|
+
const expectedFiles = [...ALLOWED_FILES].sort();
|
|
2688
|
+
const missingFiles = expectedFiles.filter((path) => !files.has(path));
|
|
2689
|
+
const unexpectedFiles = actualFiles.filter(
|
|
2690
|
+
(path) => !ALLOWED_FILES.includes(path)
|
|
2691
|
+
);
|
|
2692
|
+
if (missingFiles.length > 0 || unexpectedFiles.length > 0) {
|
|
2693
|
+
const details = [
|
|
2694
|
+
...missingFiles.length > 0 ? [`missing ${missingFiles.join(", ")}`] : [],
|
|
2695
|
+
...unexpectedFiles.length > 0 ? [`unexpected ${unexpectedFiles.join(", ")}`] : []
|
|
2696
|
+
].join("; ");
|
|
2697
|
+
throw new Error(`Rejected Claude plugin bundle: file set is not allowed (${details}).`);
|
|
2698
|
+
}
|
|
2699
|
+
const manifest = parseJsonFile(files, ".claude-plugin/plugin.json");
|
|
2700
|
+
if (manifest.name !== ORGX_CLAUDE_PLUGIN_NAME || manifest.version !== ORGX_CLAUDE_PLUGIN_VERSION) {
|
|
2701
|
+
throw new Error(
|
|
2702
|
+
`Rejected Claude plugin bundle: manifest must identify ${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_PLUGIN_VERSION}.`
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
const capabilityFields = MANIFEST_CAPABILITY_FIELDS.filter((field) => field in manifest);
|
|
2706
|
+
if (capabilityFields.length > 0) {
|
|
2707
|
+
throw new Error(
|
|
2708
|
+
`Rejected Claude plugin bundle: manifest cannot declare capability fields (${capabilityFields.join(", ")}).`
|
|
2709
|
+
);
|
|
2710
|
+
}
|
|
2711
|
+
if (canonicalizeJson(manifest) !== canonicalizeJson(EXPECTED_PLUGIN_MANIFEST)) {
|
|
2712
|
+
throw new Error(
|
|
2713
|
+
"Rejected Claude plugin bundle: manifest does not match the reviewed v0.1.12 metadata contract."
|
|
2714
|
+
);
|
|
2715
|
+
}
|
|
2716
|
+
const marketplace = parseJsonFile(files, ".claude-plugin/marketplace.json");
|
|
2717
|
+
if (marketplace.version !== ORGX_CLAUDE_PLUGIN_VERSION) {
|
|
2718
|
+
throw new Error(
|
|
2719
|
+
`Rejected Claude plugin bundle: marketplace version must be ${ORGX_CLAUDE_PLUGIN_VERSION}.`
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
const mcp = parseJsonFile(files, ".mcp.json");
|
|
2723
|
+
assertExactKeys(mcp, ["mcpServers"], ".mcp.json");
|
|
2724
|
+
const mcpServers = mcp.mcpServers;
|
|
2725
|
+
if (!mcpServers || typeof mcpServers !== "object" || Array.isArray(mcpServers)) {
|
|
2726
|
+
throw new Error("Rejected Claude plugin bundle: mcpServers must be a JSON object.");
|
|
2727
|
+
}
|
|
2728
|
+
const servers = mcpServers;
|
|
2729
|
+
assertExactKeys(servers, ["orgx"], "mcpServers");
|
|
2730
|
+
const orgx = servers.orgx;
|
|
2731
|
+
if (!orgx || typeof orgx !== "object" || Array.isArray(orgx)) {
|
|
2732
|
+
throw new Error("Rejected Claude plugin bundle: the orgx MCP server must be a JSON object.");
|
|
2733
|
+
}
|
|
2734
|
+
const orgxServer = orgx;
|
|
2735
|
+
assertExactKeys(orgxServer, ["type", "url"], "the orgx MCP server");
|
|
2736
|
+
if (orgxServer.type !== "http" || orgxServer.url !== ORGX_CLAUDE_PLUGIN_MCP_URL) {
|
|
2737
|
+
throw new Error(
|
|
2738
|
+
"Rejected Claude plugin bundle: the orgx MCP server must match the reviewed closed-world status profile endpoint."
|
|
2739
|
+
);
|
|
2740
|
+
}
|
|
2741
|
+
const combinedContent = actualFiles.map((path) => files.get(path)?.toString("utf8") ?? "").join("\n");
|
|
2742
|
+
for (const prohibited of PROHIBITED_CONTENT) {
|
|
2743
|
+
if (prohibited.pattern.test(combinedContent)) {
|
|
2744
|
+
throw new Error(
|
|
2745
|
+
`Rejected Claude plugin bundle: prohibited ${prohibited.label} content was found.`
|
|
2746
|
+
);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// src/lib/managed-plugin-tree.ts
|
|
2752
|
+
import {
|
|
2753
|
+
lstatSync,
|
|
2754
|
+
mkdirSync as mkdirSync2,
|
|
2755
|
+
mkdtempSync,
|
|
2756
|
+
readFileSync as readFileSync2,
|
|
2757
|
+
readlinkSync,
|
|
2758
|
+
readdirSync,
|
|
2759
|
+
renameSync,
|
|
2760
|
+
rmSync,
|
|
2761
|
+
writeFileSync as writeFileSync2
|
|
2762
|
+
} from "fs";
|
|
2763
|
+
import { dirname as dirname3, isAbsolute, join as join2, sep } from "path";
|
|
2764
|
+
function lstatIfExists(path) {
|
|
2765
|
+
try {
|
|
2766
|
+
return lstatSync(path);
|
|
2767
|
+
} catch (error) {
|
|
2768
|
+
const code = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
|
|
2769
|
+
if (code === "ENOENT" || code === "ENOTDIR") return null;
|
|
2770
|
+
throw error;
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
function assertSafeRelativePath(path) {
|
|
2774
|
+
const segments = path.split(/[\\/]/);
|
|
2775
|
+
const hasUnsafeSegment = segments.some(
|
|
2776
|
+
(segment) => !segment || segment === "." || segment === ".."
|
|
2777
|
+
);
|
|
2778
|
+
if (isAbsolute(path) || hasUnsafeSegment) {
|
|
2779
|
+
throw new Error(`Refusing to sync managed plugin tree: unsafe destination path '${path}'.`);
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
function occupiesExpectedManagedPath(relativePath, expectedPaths) {
|
|
2783
|
+
const descendantPrefix = `${relativePath}${sep}`;
|
|
2784
|
+
return [...expectedPaths].some(
|
|
2785
|
+
(expectedPath) => expectedPath === relativePath || expectedPath.startsWith(descendantPrefix)
|
|
2786
|
+
);
|
|
2787
|
+
}
|
|
2788
|
+
function readManagedTreeSnapshot(root, expectedPaths) {
|
|
2789
|
+
const rootStat = lstatIfExists(root);
|
|
2790
|
+
if (!rootStat) return null;
|
|
2791
|
+
if (rootStat.isSymbolicLink()) {
|
|
2792
|
+
throw new Error("Refusing to sync managed plugin tree: destination root is a symbolic link.");
|
|
2793
|
+
}
|
|
2794
|
+
if (!rootStat.isDirectory()) {
|
|
2795
|
+
throw new Error("Refusing to sync managed plugin tree: destination root is not a directory.");
|
|
2796
|
+
}
|
|
2797
|
+
const snapshot = {
|
|
2798
|
+
directories: /* @__PURE__ */ new Set(),
|
|
2799
|
+
files: /* @__PURE__ */ new Map(),
|
|
2800
|
+
symlinks: /* @__PURE__ */ new Map()
|
|
2801
|
+
};
|
|
2802
|
+
const visit = (directory, relativeDirectory) => {
|
|
2803
|
+
for (const name of readdirSync(directory)) {
|
|
2804
|
+
const path = join2(directory, name);
|
|
2805
|
+
const relativePath = relativeDirectory ? join2(relativeDirectory, name) : name;
|
|
2806
|
+
const entryStat = lstatSync(path);
|
|
2807
|
+
if (entryStat.isSymbolicLink()) {
|
|
2808
|
+
if (occupiesExpectedManagedPath(relativePath, expectedPaths)) {
|
|
2809
|
+
throw new Error(
|
|
2810
|
+
`Refusing to sync managed plugin tree: destination entry '${relativePath}' is a symbolic link.`
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
snapshot.symlinks.set(relativePath, readlinkSync(path));
|
|
2814
|
+
continue;
|
|
2815
|
+
}
|
|
2816
|
+
if (entryStat.isDirectory()) {
|
|
2817
|
+
snapshot.directories.add(relativePath);
|
|
2818
|
+
visit(path, relativePath);
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
if (entryStat.isFile()) {
|
|
2822
|
+
snapshot.files.set(relativePath, readFileSync2(path));
|
|
2823
|
+
continue;
|
|
2824
|
+
}
|
|
2825
|
+
throw new Error(
|
|
2826
|
+
`Refusing to sync managed plugin tree: destination entry '${relativePath}' is not a regular file or directory.`
|
|
2827
|
+
);
|
|
2828
|
+
}
|
|
2829
|
+
};
|
|
2830
|
+
visit(root, "");
|
|
2831
|
+
return snapshot;
|
|
2832
|
+
}
|
|
2833
|
+
function setsEqual(left, right) {
|
|
2834
|
+
return left.size === right.size && [...left].every((value) => right.has(value));
|
|
2835
|
+
}
|
|
2836
|
+
function snapshotsEqual(left, right) {
|
|
2837
|
+
if (!left || !right) return left === right;
|
|
2838
|
+
if (!setsEqual(left.directories, right.directories) || left.files.size !== right.files.size || left.symlinks.size !== right.symlinks.size) {
|
|
2839
|
+
return false;
|
|
2840
|
+
}
|
|
2841
|
+
const filesEqual = [...left.files].every(([path, bytes]) => {
|
|
2842
|
+
const other = right.files.get(path);
|
|
2843
|
+
return other !== void 0 && Buffer.compare(bytes, other) === 0;
|
|
2844
|
+
});
|
|
2845
|
+
if (!filesEqual) return false;
|
|
2846
|
+
return [...left.symlinks].every(
|
|
2847
|
+
([path, target]) => right.symlinks.get(path) === target
|
|
2848
|
+
);
|
|
2849
|
+
}
|
|
2850
|
+
function expectedDirectories(files) {
|
|
2851
|
+
const directories = /* @__PURE__ */ new Set();
|
|
2852
|
+
for (const file of files) {
|
|
2853
|
+
let current = dirname3(file.path);
|
|
2854
|
+
while (current !== "." && current !== "/") {
|
|
2855
|
+
directories.add(current);
|
|
2856
|
+
const parent = dirname3(current);
|
|
2857
|
+
if (parent === current) break;
|
|
2858
|
+
current = parent;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
return directories;
|
|
2862
|
+
}
|
|
2863
|
+
function snapshotMatchesFiles(snapshot, files) {
|
|
2864
|
+
if (!snapshot || snapshot.files.size !== files.length) return false;
|
|
2865
|
+
if (snapshot.symlinks.size > 0) return false;
|
|
2866
|
+
if (!setsEqual(snapshot.directories, expectedDirectories(files))) return false;
|
|
2867
|
+
return files.every((file) => {
|
|
2868
|
+
const existing = snapshot.files.get(file.path);
|
|
2869
|
+
return existing !== void 0 && Buffer.compare(existing, file.bytes) === 0;
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
function stageAndReplaceManagedTree(destinationRoot, files, originalSnapshot, expectedPaths) {
|
|
2873
|
+
const destinationParent = dirname3(destinationRoot);
|
|
2874
|
+
mkdirSync2(destinationParent, { recursive: true });
|
|
2875
|
+
const transactionRoot = mkdtempSync(join2(destinationParent, ".orgx-plugin-sync-"));
|
|
2876
|
+
const nextRoot = join2(transactionRoot, "next");
|
|
2877
|
+
const previousRoot = join2(transactionRoot, "previous");
|
|
2878
|
+
let preserveTransaction = false;
|
|
2879
|
+
try {
|
|
2880
|
+
mkdirSync2(nextRoot);
|
|
2881
|
+
for (const file of files) {
|
|
2882
|
+
const destination = join2(nextRoot, file.path);
|
|
2883
|
+
mkdirSync2(dirname3(destination), { recursive: true });
|
|
2884
|
+
writeFileSync2(destination, file.bytes);
|
|
2885
|
+
}
|
|
2886
|
+
const latestSnapshot = readManagedTreeSnapshot(destinationRoot, expectedPaths);
|
|
2887
|
+
if (!snapshotsEqual(originalSnapshot, latestSnapshot)) {
|
|
2888
|
+
throw new Error("Refusing to sync managed plugin tree: destination changed during staging.");
|
|
2889
|
+
}
|
|
2890
|
+
let previousMoved = false;
|
|
2891
|
+
try {
|
|
2892
|
+
if (latestSnapshot) {
|
|
2893
|
+
renameSync(destinationRoot, previousRoot);
|
|
2894
|
+
previousMoved = true;
|
|
2895
|
+
}
|
|
2896
|
+
renameSync(nextRoot, destinationRoot);
|
|
2897
|
+
if (previousMoved) {
|
|
2898
|
+
rmSync(previousRoot, { force: true, recursive: true });
|
|
2899
|
+
previousMoved = false;
|
|
2900
|
+
}
|
|
2901
|
+
} catch (error) {
|
|
2902
|
+
if (previousMoved && !lstatIfExists(destinationRoot)) {
|
|
2903
|
+
try {
|
|
2904
|
+
renameSync(previousRoot, destinationRoot);
|
|
2905
|
+
previousMoved = false;
|
|
2906
|
+
} catch (rollbackError) {
|
|
2907
|
+
preserveTransaction = true;
|
|
2908
|
+
throw new AggregateError(
|
|
2909
|
+
[error, rollbackError],
|
|
2910
|
+
`Managed plugin replacement failed and rollback could not restore the prior tree. Recovery data remains at ${transactionRoot}.`
|
|
2911
|
+
);
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
throw error;
|
|
2915
|
+
}
|
|
2916
|
+
} finally {
|
|
2917
|
+
if (!preserveTransaction) {
|
|
2918
|
+
rmSync(transactionRoot, { force: true, recursive: true });
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
function replaceManagedPluginTreeIfChanged(destinationRoot, files) {
|
|
2923
|
+
const paths = /* @__PURE__ */ new Set();
|
|
2924
|
+
for (const file of files) {
|
|
2925
|
+
assertSafeRelativePath(file.path);
|
|
2926
|
+
if (paths.has(file.path)) {
|
|
2927
|
+
throw new Error(`Refusing to sync managed plugin tree: duplicate destination path '${file.path}'.`);
|
|
2928
|
+
}
|
|
2929
|
+
paths.add(file.path);
|
|
2930
|
+
}
|
|
2931
|
+
const snapshot = readManagedTreeSnapshot(destinationRoot, paths);
|
|
2932
|
+
if (snapshotMatchesFiles(snapshot, files)) return false;
|
|
2933
|
+
stageAndReplaceManagedTree(destinationRoot, files, snapshot, paths);
|
|
2934
|
+
return true;
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2547
2937
|
// src/lib/skills.ts
|
|
2548
2938
|
import { createHash as createHash2 } from "crypto";
|
|
2549
|
-
import { existsSync as existsSync3, readdirSync } from "fs";
|
|
2550
|
-
import { basename, join as
|
|
2939
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
2940
|
+
import { basename, join as join3 } from "path";
|
|
2551
2941
|
var DEFAULT_ORGX_SKILL_PACKS = [
|
|
2552
2942
|
"morning-briefing",
|
|
2553
2943
|
"initiative-kickoff",
|
|
@@ -2645,7 +3035,7 @@ function defaultExtensionTitle(skillId, scope) {
|
|
|
2645
3035
|
return `${prefix} ${skillId} behavior`;
|
|
2646
3036
|
}
|
|
2647
3037
|
function extensionFilePath(skillId, scope, extensionsDir = ORGX_SKILL_EXTENSIONS_DIR) {
|
|
2648
|
-
return
|
|
3038
|
+
return join3(extensionsDir, `${scope}.${skillId}.md`);
|
|
2649
3039
|
}
|
|
2650
3040
|
function extensionTemplate(input) {
|
|
2651
3041
|
const body = input.content?.trim() ? input.content.trim() : [
|
|
@@ -2729,8 +3119,8 @@ function listSkillExtensions(options = {}) {
|
|
|
2729
3119
|
if (!existsSync3(extensionsDir)) {
|
|
2730
3120
|
return [];
|
|
2731
3121
|
}
|
|
2732
|
-
return
|
|
2733
|
-
const path =
|
|
3122
|
+
return readdirSync2(extensionsDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => {
|
|
3123
|
+
const path = join3(extensionsDir, entry.name);
|
|
2734
3124
|
const content = readTextIfExists(path);
|
|
2735
3125
|
return content === null ? null : parseSkillExtension(path, content);
|
|
2736
3126
|
}).filter((entry) => Boolean(entry)).sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -3002,7 +3392,7 @@ async function installSkillPack(skillName, claudeSkillsDir, fetchImpl, ref, trac
|
|
|
3002
3392
|
const content = relativePath === "SKILL.md" ? composeSkillContent(skillName, coreContent, tracking.extensions) : coreContent;
|
|
3003
3393
|
writes.push(
|
|
3004
3394
|
writeManagedFile(
|
|
3005
|
-
|
|
3395
|
+
join3(claudeSkillsDir, skillName, relativePath),
|
|
3006
3396
|
content,
|
|
3007
3397
|
`${skillName}/${relativePath}`,
|
|
3008
3398
|
file.sourceUrl,
|
|
@@ -3141,8 +3531,6 @@ function getSkillStatus(options = {}) {
|
|
|
3141
3531
|
var DEFAULT_ORGX_PLUGIN_TARGETS = ["cursor", "claude", "codex", "openclaw"];
|
|
3142
3532
|
var ORGX_PLUGIN_GITHUB_OWNER = "useorgx";
|
|
3143
3533
|
var ORGX_PLUGIN_GITHUB_REF = "main";
|
|
3144
|
-
var ORGX_CLAUDE_PLUGIN_NAME = "orgx-claude-code-plugin";
|
|
3145
|
-
var ORGX_CLAUDE_MARKETPLACE_NAME = "orgx-local";
|
|
3146
3534
|
var ORGX_CODEX_PLUGIN_NAME = "orgx-codex-plugin";
|
|
3147
3535
|
var ORGX_CURSOR_PLUGIN_NAME = "cursor-plugin";
|
|
3148
3536
|
var ORGX_OPENCLAW_PLUGIN_ID = "orgx";
|
|
@@ -3150,16 +3538,14 @@ var ORGX_OPENCLAW_PLUGIN_PACKAGE_NAME = "@useorgx/openclaw-plugin";
|
|
|
3150
3538
|
var CLAUDE_PLUGIN_SYNC_SPEC = {
|
|
3151
3539
|
owner: ORGX_PLUGIN_GITHUB_OWNER,
|
|
3152
3540
|
repo: ORGX_CLAUDE_PLUGIN_NAME,
|
|
3153
|
-
ref:
|
|
3541
|
+
ref: ORGX_CLAUDE_PLUGIN_REF,
|
|
3154
3542
|
include: [
|
|
3155
3543
|
{ localPath: ".claude-plugin", remotePath: ".claude-plugin" },
|
|
3156
|
-
{ localPath: "
|
|
3544
|
+
{ localPath: ".mcp.json", remotePath: ".mcp.json" },
|
|
3157
3545
|
{ localPath: "commands", remotePath: "commands" },
|
|
3158
|
-
{ localPath: "hooks", remotePath: "hooks" },
|
|
3159
|
-
{ localPath: "lib", remotePath: "lib" },
|
|
3160
|
-
{ localPath: "scripts", remotePath: "scripts" },
|
|
3161
3546
|
{ localPath: "skills", remotePath: "skills" }
|
|
3162
|
-
]
|
|
3547
|
+
],
|
|
3548
|
+
validate: validateClaudePluginBundle
|
|
3163
3549
|
};
|
|
3164
3550
|
var CODEX_PLUGIN_SYNC_SPEC = {
|
|
3165
3551
|
owner: ORGX_PLUGIN_GITHUB_OWNER,
|
|
@@ -3282,7 +3668,7 @@ async function listRemoteRepoFiles(spec, path, localPath, fetchImpl) {
|
|
|
3282
3668
|
...await listRemoteRepoFiles(
|
|
3283
3669
|
spec,
|
|
3284
3670
|
entry.path,
|
|
3285
|
-
|
|
3671
|
+
join4(localPath, entry.name),
|
|
3286
3672
|
fetchImpl
|
|
3287
3673
|
)
|
|
3288
3674
|
);
|
|
@@ -3292,7 +3678,7 @@ async function listRemoteRepoFiles(spec, path, localPath, fetchImpl) {
|
|
|
3292
3678
|
throw new Error(`GitHub did not provide a download URL for '${entry.path}'.`);
|
|
3293
3679
|
}
|
|
3294
3680
|
files.push({
|
|
3295
|
-
localPath:
|
|
3681
|
+
localPath: join4(localPath, entry.name),
|
|
3296
3682
|
path: entry.path,
|
|
3297
3683
|
sourceUrl: entry.download_url
|
|
3298
3684
|
});
|
|
@@ -3328,88 +3714,25 @@ async function fetchRemoteBytes(sourceUrl, fetchImpl) {
|
|
|
3328
3714
|
}
|
|
3329
3715
|
return Buffer.from(await response.arrayBuffer());
|
|
3330
3716
|
}
|
|
3331
|
-
function readBytesIfExists(path) {
|
|
3332
|
-
if (!existsSync4(path)) return null;
|
|
3333
|
-
try {
|
|
3334
|
-
if (!statSync2(path).isFile()) {
|
|
3335
|
-
return null;
|
|
3336
|
-
}
|
|
3337
|
-
return readFileSync2(path);
|
|
3338
|
-
} catch (error) {
|
|
3339
|
-
const code = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
|
|
3340
|
-
if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR") {
|
|
3341
|
-
return null;
|
|
3342
|
-
}
|
|
3343
|
-
throw error;
|
|
3344
|
-
}
|
|
3345
|
-
}
|
|
3346
|
-
function writeBytesIfChanged(path, bytes) {
|
|
3347
|
-
const existing = readBytesIfExists(path);
|
|
3348
|
-
if (existing && Buffer.compare(existing, bytes) === 0) {
|
|
3349
|
-
return false;
|
|
3350
|
-
}
|
|
3351
|
-
mkdirSync2(dirname3(path), { recursive: true });
|
|
3352
|
-
writeFileSync2(path, bytes);
|
|
3353
|
-
return true;
|
|
3354
|
-
}
|
|
3355
3717
|
function removePathIfExists(path) {
|
|
3356
3718
|
if (!existsSync4(path)) return false;
|
|
3357
|
-
|
|
3719
|
+
rmSync2(path, { force: true, recursive: true });
|
|
3358
3720
|
return true;
|
|
3359
3721
|
}
|
|
3360
|
-
function listRelativeFiles(root, base = root) {
|
|
3361
|
-
if (!existsSync4(root)) return [];
|
|
3362
|
-
if (!statSync2(root).isDirectory()) {
|
|
3363
|
-
return [];
|
|
3364
|
-
}
|
|
3365
|
-
const files = [];
|
|
3366
|
-
for (const entry of readdirSync2(root, { withFileTypes: true })) {
|
|
3367
|
-
const nextPath = join3(root, entry.name);
|
|
3368
|
-
if (entry.isDirectory()) {
|
|
3369
|
-
files.push(...listRelativeFiles(nextPath, base));
|
|
3370
|
-
continue;
|
|
3371
|
-
}
|
|
3372
|
-
if (entry.isFile()) {
|
|
3373
|
-
files.push(relative(base, nextPath));
|
|
3374
|
-
}
|
|
3375
|
-
}
|
|
3376
|
-
return files.sort();
|
|
3377
|
-
}
|
|
3378
|
-
function pruneEmptyDirectories(root, current = root) {
|
|
3379
|
-
if (!existsSync4(current) || !statSync2(current).isDirectory()) {
|
|
3380
|
-
return false;
|
|
3381
|
-
}
|
|
3382
|
-
let changed = false;
|
|
3383
|
-
for (const entry of readdirSync2(current, { withFileTypes: true })) {
|
|
3384
|
-
if (!entry.isDirectory()) continue;
|
|
3385
|
-
changed = pruneEmptyDirectories(root, join3(current, entry.name)) || changed;
|
|
3386
|
-
}
|
|
3387
|
-
if (current !== root && readdirSync2(current).length === 0) {
|
|
3388
|
-
rmSync(current, { force: true, recursive: true });
|
|
3389
|
-
return true;
|
|
3390
|
-
}
|
|
3391
|
-
return changed;
|
|
3392
|
-
}
|
|
3393
3722
|
async function syncManagedRepoTree(spec, destinationRoot, fetchImpl) {
|
|
3394
3723
|
const remoteFiles = await collectRemoteRepoFiles(spec, fetchImpl);
|
|
3395
|
-
|
|
3396
|
-
const expected = new Set(remoteFiles.map((file) => file.localPath));
|
|
3397
|
-
if (existsSync4(destinationRoot) && !statSync2(destinationRoot).isDirectory()) {
|
|
3398
|
-
rmSync(destinationRoot, { force: true, recursive: true });
|
|
3399
|
-
changed = true;
|
|
3400
|
-
}
|
|
3401
|
-
for (const file of listRelativeFiles(destinationRoot)) {
|
|
3402
|
-
if (expected.has(file)) continue;
|
|
3403
|
-
rmSync(join3(destinationRoot, file), { force: true });
|
|
3404
|
-
changed = true;
|
|
3405
|
-
}
|
|
3406
|
-
changed = pruneEmptyDirectories(destinationRoot) || changed;
|
|
3724
|
+
const fetchedFiles = [];
|
|
3407
3725
|
for (const file of remoteFiles) {
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
}
|
|
3726
|
+
fetchedFiles.push({
|
|
3727
|
+
...file,
|
|
3728
|
+
bytes: await fetchRemoteBytes(file.sourceUrl, fetchImpl)
|
|
3729
|
+
});
|
|
3412
3730
|
}
|
|
3731
|
+
spec.validate?.(new Map(fetchedFiles.map((file) => [file.localPath, file.bytes])));
|
|
3732
|
+
const changed = replaceManagedPluginTreeIfChanged(
|
|
3733
|
+
destinationRoot,
|
|
3734
|
+
fetchedFiles.map((file) => ({ path: file.localPath, bytes: file.bytes }))
|
|
3735
|
+
);
|
|
3413
3736
|
return { changed, fileCount: remoteFiles.length };
|
|
3414
3737
|
}
|
|
3415
3738
|
function serializeJson(value) {
|
|
@@ -3422,8 +3745,8 @@ function writeJsonIfChanged(path, value) {
|
|
|
3422
3745
|
if (existing === next) {
|
|
3423
3746
|
return false;
|
|
3424
3747
|
}
|
|
3425
|
-
|
|
3426
|
-
|
|
3748
|
+
mkdirSync3(dirname4(path), { recursive: true });
|
|
3749
|
+
writeFileSync3(path, next, "utf8");
|
|
3427
3750
|
return true;
|
|
3428
3751
|
}
|
|
3429
3752
|
function buildClaudeMarketplaceManifest() {
|
|
@@ -3437,7 +3760,7 @@ function buildClaudeMarketplaceManifest() {
|
|
|
3437
3760
|
plugins: [
|
|
3438
3761
|
{
|
|
3439
3762
|
name: ORGX_CLAUDE_PLUGIN_NAME,
|
|
3440
|
-
description: "
|
|
3763
|
+
description: "Connect Claude Code to a focused, non-destructive, closed-world OrgX status profile through native OAuth.",
|
|
3441
3764
|
source: `./plugins/${ORGX_CLAUDE_PLUGIN_NAME}`
|
|
3442
3765
|
}
|
|
3443
3766
|
]
|
|
@@ -3494,7 +3817,7 @@ function removeCodexMarketplaceEntry(path) {
|
|
|
3494
3817
|
return false;
|
|
3495
3818
|
}
|
|
3496
3819
|
if (nextPlugins.length === 0) {
|
|
3497
|
-
|
|
3820
|
+
rmSync2(path, { force: true });
|
|
3498
3821
|
return true;
|
|
3499
3822
|
}
|
|
3500
3823
|
return writeJsonIfChanged(path, {
|
|
@@ -3506,16 +3829,21 @@ function codexMarketplaceHasOrgxEntry(path) {
|
|
|
3506
3829
|
const { plugins } = readMarketplacePlugins(path);
|
|
3507
3830
|
return plugins.some((plugin) => plugin.name === ORGX_CODEX_PLUGIN_NAME);
|
|
3508
3831
|
}
|
|
3509
|
-
function
|
|
3832
|
+
function extractClaudePluginInstallations(payload) {
|
|
3510
3833
|
try {
|
|
3511
3834
|
const parsed = JSON.parse(payload);
|
|
3512
3835
|
if (!Array.isArray(parsed)) return [];
|
|
3513
3836
|
return parsed.flatMap((entry) => {
|
|
3514
|
-
if (typeof entry === "string") return [entry];
|
|
3837
|
+
if (typeof entry === "string") return [{ id: entry }];
|
|
3515
3838
|
if (!entry || typeof entry !== "object") return [];
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
return [];
|
|
3839
|
+
const item = entry;
|
|
3840
|
+
const id = typeof item.id === "string" ? item.id : typeof item.name === "string" ? item.name : void 0;
|
|
3841
|
+
if (!id) return [];
|
|
3842
|
+
return [{
|
|
3843
|
+
id,
|
|
3844
|
+
...typeof item.scope === "string" ? { scope: item.scope } : {},
|
|
3845
|
+
...typeof item.version === "string" ? { version: item.version } : {}
|
|
3846
|
+
}];
|
|
3519
3847
|
});
|
|
3520
3848
|
} catch {
|
|
3521
3849
|
return [];
|
|
@@ -3600,11 +3928,30 @@ async function getClaudeInstallState(runner) {
|
|
|
3600
3928
|
if (result.exitCode !== 0) {
|
|
3601
3929
|
return { available: true, installed: false };
|
|
3602
3930
|
}
|
|
3931
|
+
const managedPluginId = `${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`;
|
|
3932
|
+
const installation = extractClaudePluginInstallations(result.stdout).find(
|
|
3933
|
+
(plugin) => plugin.id === managedPluginId && plugin.scope === "user"
|
|
3934
|
+
);
|
|
3603
3935
|
return {
|
|
3604
3936
|
available: true,
|
|
3605
|
-
installed:
|
|
3937
|
+
installed: Boolean(installation),
|
|
3938
|
+
...installation?.version ? { version: installation.version } : {}
|
|
3606
3939
|
};
|
|
3607
3940
|
}
|
|
3941
|
+
async function requireManagedClaudePluginVersion(runner, operation) {
|
|
3942
|
+
const state = await getClaudeInstallState(runner);
|
|
3943
|
+
if (!state.installed) {
|
|
3944
|
+
throw new Error(
|
|
3945
|
+
`Claude plugin ${operation} completed, but Claude Code does not report ${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME} as installed at user scope.`
|
|
3946
|
+
);
|
|
3947
|
+
}
|
|
3948
|
+
if (state.version !== ORGX_CLAUDE_PLUGIN_VERSION) {
|
|
3949
|
+
throw new Error(
|
|
3950
|
+
`Claude plugin ${operation} completed, but Claude Code reports version ${state.version ?? "unknown"}; expected ${ORGX_CLAUDE_PLUGIN_VERSION}.`
|
|
3951
|
+
);
|
|
3952
|
+
}
|
|
3953
|
+
return state;
|
|
3954
|
+
}
|
|
3608
3955
|
async function getOpenclawInstallState(runner) {
|
|
3609
3956
|
const available = detectSurface("openclaw").detected || await commandExists("openclaw", runner);
|
|
3610
3957
|
if (!available) {
|
|
@@ -3620,17 +3967,17 @@ async function getOpenclawInstallState(runner) {
|
|
|
3620
3967
|
};
|
|
3621
3968
|
}
|
|
3622
3969
|
function cursorPluginManifestPath(paths) {
|
|
3623
|
-
return
|
|
3970
|
+
return join4(paths.cursorPluginDir, ".cursor-plugin", "plugin.json");
|
|
3624
3971
|
}
|
|
3625
3972
|
function cursorPluginMcpPath(paths) {
|
|
3626
|
-
return
|
|
3973
|
+
return join4(paths.cursorPluginDir, ".mcp.json");
|
|
3627
3974
|
}
|
|
3628
3975
|
function isCursorPluginInstalled(paths) {
|
|
3629
3976
|
return existsSync4(cursorPluginManifestPath(paths)) && existsSync4(cursorPluginMcpPath(paths));
|
|
3630
3977
|
}
|
|
3631
3978
|
function getCursorToolingState(options = {}) {
|
|
3632
3979
|
const paths = resolvePluginPaths(options.paths);
|
|
3633
|
-
const mcpFile = options.mcpPath ?? CURSOR_MCP_PATH ??
|
|
3980
|
+
const mcpFile = options.mcpPath ?? CURSOR_MCP_PATH ?? join4(CURSOR_DIR, "mcp.json");
|
|
3634
3981
|
const mcpText = readTextIfExists(mcpFile);
|
|
3635
3982
|
const inspection = inspectCursorMcpConfig(mcpText);
|
|
3636
3983
|
return {
|
|
@@ -3640,7 +3987,7 @@ function getCursorToolingState(options = {}) {
|
|
|
3640
3987
|
};
|
|
3641
3988
|
}
|
|
3642
3989
|
function isCursorPluginAvailable(paths) {
|
|
3643
|
-
return detectSurface("cursor").detected || existsSync4(paths.cursorPluginDir) || existsSync4(
|
|
3990
|
+
return detectSurface("cursor").detected || existsSync4(paths.cursorPluginDir) || existsSync4(dirname4(paths.cursorPluginDir)) || readTextIfExists(paths.cursorRulePath) !== null;
|
|
3644
3991
|
}
|
|
3645
3992
|
function buildCursorStatus(paths) {
|
|
3646
3993
|
const existingRules = readTextIfExists(paths.cursorRulePath);
|
|
@@ -3826,36 +4173,44 @@ async function installClaudePlugin(paths, fetchImpl, runner) {
|
|
|
3826
4173
|
throw new Error(formatCommandFailure("claude", ["plugin", "marketplace", "add", paths.claudeMarketplaceDir], marketplaceAdd));
|
|
3827
4174
|
}
|
|
3828
4175
|
let installedChanged = false;
|
|
4176
|
+
let updatedChanged = false;
|
|
3829
4177
|
if (!state.installed) {
|
|
3830
|
-
const
|
|
4178
|
+
const installArgs = [
|
|
3831
4179
|
"plugin",
|
|
3832
4180
|
"install",
|
|
3833
4181
|
`${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`,
|
|
3834
4182
|
"--scope",
|
|
3835
4183
|
"user"
|
|
3836
|
-
]
|
|
4184
|
+
];
|
|
4185
|
+
const install = await runner("claude", installArgs);
|
|
3837
4186
|
if (install.exitCode !== 0) {
|
|
3838
4187
|
throw new Error(
|
|
3839
|
-
formatCommandFailure(
|
|
3840
|
-
"claude",
|
|
3841
|
-
[
|
|
3842
|
-
"plugin",
|
|
3843
|
-
"install",
|
|
3844
|
-
`${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`,
|
|
3845
|
-
"--scope",
|
|
3846
|
-
"user"
|
|
3847
|
-
],
|
|
3848
|
-
install
|
|
3849
|
-
)
|
|
4188
|
+
formatCommandFailure("claude", installArgs, install)
|
|
3850
4189
|
);
|
|
3851
4190
|
}
|
|
4191
|
+
await requireManagedClaudePluginVersion(runner, "install");
|
|
3852
4192
|
installedChanged = true;
|
|
4193
|
+
} else {
|
|
4194
|
+
const updateArgs = [
|
|
4195
|
+
"plugin",
|
|
4196
|
+
"update",
|
|
4197
|
+
`${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`,
|
|
4198
|
+
"--scope",
|
|
4199
|
+
"user"
|
|
4200
|
+
];
|
|
4201
|
+
const update = await runner("claude", updateArgs);
|
|
4202
|
+
if (update.exitCode !== 0) {
|
|
4203
|
+
throw new Error(formatCommandFailure("claude", updateArgs, update));
|
|
4204
|
+
}
|
|
4205
|
+
await requireManagedClaudePluginVersion(runner, "update");
|
|
4206
|
+
updatedChanged = state.version !== ORGX_CLAUDE_PLUGIN_VERSION;
|
|
3853
4207
|
}
|
|
3854
|
-
const changed = syncResult.changed || manifestChanged || installedChanged;
|
|
4208
|
+
const changed = syncResult.changed || manifestChanged || installedChanged || updatedChanged;
|
|
4209
|
+
const operationMessage = installedChanged ? `installed version ${ORGX_CLAUDE_PLUGIN_VERSION}` : updatedChanged ? `updated the Claude cache from ${state.version ?? "an older version"} to ${ORGX_CLAUDE_PLUGIN_VERSION}` : "confirmed the Claude cache is current";
|
|
3855
4210
|
return {
|
|
3856
4211
|
target: "claude",
|
|
3857
4212
|
changed,
|
|
3858
|
-
message: changed ? `Synced ${syncResult.fileCount} Claude plugin files and
|
|
4213
|
+
message: changed ? `Synced ${syncResult.fileCount} Claude plugin files and ${operationMessage}.` : `Claude Code plugin ${ORGX_CLAUDE_PLUGIN_VERSION} is already installed and up to date.`
|
|
3859
4214
|
};
|
|
3860
4215
|
}
|
|
3861
4216
|
async function installCodexPlugin(paths, fetchImpl, runner) {
|
|
@@ -3894,10 +4249,10 @@ async function installOpenclawPlugin(fetchImpl, runner) {
|
|
|
3894
4249
|
}
|
|
3895
4250
|
const { tarballUrl, version } = await resolveOpenclawTarball(fetchImpl);
|
|
3896
4251
|
const tarballBytes = await fetchRemoteBytes(tarballUrl, fetchImpl);
|
|
3897
|
-
const tempRoot =
|
|
3898
|
-
const archivePath =
|
|
4252
|
+
const tempRoot = mkdtempSync2(join4(tmpdir(), "orgx-wizard-openclaw-"));
|
|
4253
|
+
const archivePath = join4(tempRoot, `orgx-openclaw-plugin-${version}.tgz`);
|
|
3899
4254
|
try {
|
|
3900
|
-
|
|
4255
|
+
writeFileSync3(archivePath, tarballBytes);
|
|
3901
4256
|
const install = await runner("openclaw", ["plugins", "install", archivePath]);
|
|
3902
4257
|
if (install.exitCode !== 0) {
|
|
3903
4258
|
throw new Error(
|
|
@@ -3905,7 +4260,7 @@ async function installOpenclawPlugin(fetchImpl, runner) {
|
|
|
3905
4260
|
);
|
|
3906
4261
|
}
|
|
3907
4262
|
} finally {
|
|
3908
|
-
|
|
4263
|
+
rmSync2(tempRoot, { force: true, recursive: true });
|
|
3909
4264
|
}
|
|
3910
4265
|
return {
|
|
3911
4266
|
target: "openclaw",
|
|
@@ -4079,6 +4434,134 @@ function countPluginReportChanges(report) {
|
|
|
4079
4434
|
return report.results.filter((result) => result.changed).length;
|
|
4080
4435
|
}
|
|
4081
4436
|
|
|
4437
|
+
// src/surfaces/deepseek.ts
|
|
4438
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
4439
|
+
var DEEPSEEK_HARNESS_VERSION = "0.1.0-rc.6";
|
|
4440
|
+
var DEEPSEEK_ORGX_PLUGIN = "@useorgx/deepseek-harness-plugin";
|
|
4441
|
+
var DEEPSEEK_ORGX_PLUGIN_VERSION = "0.1.0";
|
|
4442
|
+
var DEEPSEEK_PROFILE = "headless";
|
|
4443
|
+
var runDeepseekCommand = (command, args) => {
|
|
4444
|
+
const result = spawnSync3(command, [...args], {
|
|
4445
|
+
encoding: "utf8",
|
|
4446
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4447
|
+
timeout: 3e4
|
|
4448
|
+
});
|
|
4449
|
+
return {
|
|
4450
|
+
status: result.status,
|
|
4451
|
+
stdout: result.stdout ?? "",
|
|
4452
|
+
stderr: result.stderr ?? "",
|
|
4453
|
+
...result.error ? { error: result.error } : {}
|
|
4454
|
+
};
|
|
4455
|
+
};
|
|
4456
|
+
function normalizeVersionOutput(value) {
|
|
4457
|
+
const normalized = value.trim();
|
|
4458
|
+
return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(normalized) ? normalized : void 0;
|
|
4459
|
+
}
|
|
4460
|
+
function inspectDeepseekRuntime(runner = runDeepseekCommand) {
|
|
4461
|
+
const result = runner("dsh", ["--version"]);
|
|
4462
|
+
const version = normalizeVersionOutput(result.stdout);
|
|
4463
|
+
if (result.status !== 0 || !version) {
|
|
4464
|
+
return {
|
|
4465
|
+
installed: false,
|
|
4466
|
+
supported: false,
|
|
4467
|
+
details: [
|
|
4468
|
+
result.error?.message ?? (result.stderr.trim() || "dsh --version did not return a version")
|
|
4469
|
+
]
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
const supported = version === DEEPSEEK_HARNESS_VERSION;
|
|
4473
|
+
return {
|
|
4474
|
+
installed: true,
|
|
4475
|
+
supported,
|
|
4476
|
+
version,
|
|
4477
|
+
details: [
|
|
4478
|
+
supported ? `DeepSeek Harness ${version} detected` : `DeepSeek Harness ${version} detected; OrgX currently requires ${DEEPSEEK_HARNESS_VERSION}`
|
|
4479
|
+
]
|
|
4480
|
+
};
|
|
4481
|
+
}
|
|
4482
|
+
function readDependencyVersion(raw) {
|
|
4483
|
+
if (!raw) return void 0;
|
|
4484
|
+
try {
|
|
4485
|
+
const parsed = JSON.parse(raw);
|
|
4486
|
+
for (const key of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
|
4487
|
+
const dependencies = parsed[key];
|
|
4488
|
+
if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) {
|
|
4489
|
+
continue;
|
|
4490
|
+
}
|
|
4491
|
+
const version = dependencies[DEEPSEEK_ORGX_PLUGIN];
|
|
4492
|
+
if (typeof version === "string" && version.trim()) return version.trim();
|
|
4493
|
+
}
|
|
4494
|
+
} catch {
|
|
4495
|
+
return void 0;
|
|
4496
|
+
}
|
|
4497
|
+
return void 0;
|
|
4498
|
+
}
|
|
4499
|
+
function inspectDeepseekPlugin(profileManifestPath) {
|
|
4500
|
+
const version = readDependencyVersion(readTextIfExists(profileManifestPath));
|
|
4501
|
+
return {
|
|
4502
|
+
installed: Boolean(version),
|
|
4503
|
+
...version ? { version } : {},
|
|
4504
|
+
details: [
|
|
4505
|
+
version ? `${DEEPSEEK_ORGX_PLUGIN} ${version} is installed in the ${DEEPSEEK_PROFILE} profile` : `${DEEPSEEK_ORGX_PLUGIN} is not installed in the ${DEEPSEEK_PROFILE} profile`
|
|
4506
|
+
]
|
|
4507
|
+
};
|
|
4508
|
+
}
|
|
4509
|
+
function installDeepseekPlugin(profileManifestPath, runner = runDeepseekCommand) {
|
|
4510
|
+
const runtime = inspectDeepseekRuntime(runner);
|
|
4511
|
+
if (!runtime.installed) {
|
|
4512
|
+
return {
|
|
4513
|
+
changed: false,
|
|
4514
|
+
message: `DeepSeek Harness was not found. Install @deepseek-ai/dsh@${DEEPSEEK_HARNESS_VERSION}, then run setup again.`
|
|
4515
|
+
};
|
|
4516
|
+
}
|
|
4517
|
+
if (!runtime.supported) {
|
|
4518
|
+
return {
|
|
4519
|
+
changed: false,
|
|
4520
|
+
message: `DeepSeek Harness ${runtime.version ?? "unknown"} is not supported; OrgX requires ${DEEPSEEK_HARNESS_VERSION}.`
|
|
4521
|
+
};
|
|
4522
|
+
}
|
|
4523
|
+
const before = inspectDeepseekPlugin(profileManifestPath);
|
|
4524
|
+
if (before.installed && before.version === DEEPSEEK_ORGX_PLUGIN_VERSION) {
|
|
4525
|
+
return {
|
|
4526
|
+
changed: false,
|
|
4527
|
+
message: `${DEEPSEEK_ORGX_PLUGIN}@${DEEPSEEK_ORGX_PLUGIN_VERSION} is already installed.`
|
|
4528
|
+
};
|
|
4529
|
+
}
|
|
4530
|
+
const spec = `${DEEPSEEK_ORGX_PLUGIN}@${DEEPSEEK_ORGX_PLUGIN_VERSION}`;
|
|
4531
|
+
const result = runner("dsh", ["plugin", "--profile", DEEPSEEK_PROFILE, "add", spec]);
|
|
4532
|
+
if (result.status !== 0) {
|
|
4533
|
+
const detail = result.stderr.trim() || result.error?.message || `exit ${result.status ?? "unknown"}`;
|
|
4534
|
+
throw new Error(`Could not install ${spec}: ${detail}`);
|
|
4535
|
+
}
|
|
4536
|
+
return {
|
|
4537
|
+
changed: true,
|
|
4538
|
+
message: `${spec} installed in the ${DEEPSEEK_PROFILE} profile.`
|
|
4539
|
+
};
|
|
4540
|
+
}
|
|
4541
|
+
function removeDeepseekPlugin(profileManifestPath, runner = runDeepseekCommand) {
|
|
4542
|
+
if (!inspectDeepseekPlugin(profileManifestPath).installed) {
|
|
4543
|
+
return {
|
|
4544
|
+
changed: false,
|
|
4545
|
+
message: `${DEEPSEEK_ORGX_PLUGIN} is not installed.`
|
|
4546
|
+
};
|
|
4547
|
+
}
|
|
4548
|
+
const result = runner("dsh", [
|
|
4549
|
+
"plugin",
|
|
4550
|
+
"--profile",
|
|
4551
|
+
DEEPSEEK_PROFILE,
|
|
4552
|
+
"remove",
|
|
4553
|
+
DEEPSEEK_ORGX_PLUGIN
|
|
4554
|
+
]);
|
|
4555
|
+
if (result.status !== 0) {
|
|
4556
|
+
const detail = result.stderr.trim() || result.error?.message || `exit ${result.status ?? "unknown"}`;
|
|
4557
|
+
throw new Error(`Could not remove ${DEEPSEEK_ORGX_PLUGIN}: ${detail}`);
|
|
4558
|
+
}
|
|
4559
|
+
return {
|
|
4560
|
+
changed: true,
|
|
4561
|
+
message: `${DEEPSEEK_ORGX_PLUGIN} removed from the ${DEEPSEEK_PROFILE} profile.`
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4564
|
+
|
|
4082
4565
|
// src/surfaces/registry.ts
|
|
4083
4566
|
var AUTH_SETUP_HINT = "orgx-wizard auth login";
|
|
4084
4567
|
var AUTH_SET_KEY_HINT = "orgx-wizard auth set-key";
|
|
@@ -4113,6 +4596,19 @@ function automatedSurfaceStatus(name) {
|
|
|
4113
4596
|
const detection = detectSurface(name);
|
|
4114
4597
|
const path = detection.existingPath ?? detection.preferredPath;
|
|
4115
4598
|
const openclaw = getOpenClawDependencyState();
|
|
4599
|
+
if (name === "deepseek") {
|
|
4600
|
+
const runtime = inspectDeepseekRuntime();
|
|
4601
|
+
const plugin = path ? inspectDeepseekPlugin(path) : { installed: false, details: ["DeepSeek profile path is unavailable"] };
|
|
4602
|
+
return {
|
|
4603
|
+
name,
|
|
4604
|
+
mode: "automated",
|
|
4605
|
+
detected: detection.detected || runtime.installed,
|
|
4606
|
+
configured: runtime.supported && plugin.installed,
|
|
4607
|
+
...path ? { path } : {},
|
|
4608
|
+
details: [...runtime.details, ...plugin.details, ...detection.evidence],
|
|
4609
|
+
summary: !runtime.installed ? "DeepSeek Harness was not detected." : !runtime.supported ? "DeepSeek Harness is installed, but the version is not supported by the OrgX plugin." : plugin.installed ? "OrgX is installed in the DeepSeek Harness headless profile." : "DeepSeek Harness is ready for the OrgX plugin."
|
|
4610
|
+
};
|
|
4611
|
+
}
|
|
4116
4612
|
if (name === "claude") {
|
|
4117
4613
|
const inspection2 = inspectClaudeMcpConfig(path ? readTextIfExists(path) : null);
|
|
4118
4614
|
const configured = inspection2.hostedConfigured === true && (openclaw.detected ? inspection2.localConfigured === true : true);
|
|
@@ -4400,6 +4896,15 @@ async function addAutomatedSurface(name) {
|
|
|
4400
4896
|
message: openclaw.detected ? "OrgX is connected in Codex with the local OpenClaw bridge." : "OrgX cloud MCP is connected in Codex."
|
|
4401
4897
|
};
|
|
4402
4898
|
}
|
|
4899
|
+
case "deepseek": {
|
|
4900
|
+
const result = installDeepseekPlugin(path);
|
|
4901
|
+
return {
|
|
4902
|
+
name,
|
|
4903
|
+
changed: result.changed,
|
|
4904
|
+
path,
|
|
4905
|
+
message: result.message
|
|
4906
|
+
};
|
|
4907
|
+
}
|
|
4403
4908
|
case "openclaw": {
|
|
4404
4909
|
const previous = readTextIfExists(path);
|
|
4405
4910
|
const auth = await resolveOrgxAuth();
|
|
@@ -4497,6 +5002,15 @@ function removeAutomatedSurface(name) {
|
|
|
4497
5002
|
message: "OrgX connection was removed from Codex."
|
|
4498
5003
|
};
|
|
4499
5004
|
}
|
|
5005
|
+
case "deepseek": {
|
|
5006
|
+
const result = removeDeepseekPlugin(path);
|
|
5007
|
+
return {
|
|
5008
|
+
name,
|
|
5009
|
+
changed: result.changed,
|
|
5010
|
+
path,
|
|
5011
|
+
message: result.message
|
|
5012
|
+
};
|
|
5013
|
+
}
|
|
4500
5014
|
case "openclaw": {
|
|
4501
5015
|
const previous = readTextIfExists(path);
|
|
4502
5016
|
const next = removeOpenClawConfig(previous);
|
|
@@ -5230,8 +5744,8 @@ async function ensureOnboardingTask(workspace, options = {}) {
|
|
|
5230
5744
|
|
|
5231
5745
|
// src/lib/local-skill-discovery.ts
|
|
5232
5746
|
import { createHash as createHash3 } from "crypto";
|
|
5233
|
-
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as
|
|
5234
|
-
import { basename as basename2, join as
|
|
5747
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
5748
|
+
import { basename as basename2, join as join5, relative } from "path";
|
|
5235
5749
|
var DEFAULT_MAX_BYTES = 48e3;
|
|
5236
5750
|
var DEFAULT_LIMIT = 12;
|
|
5237
5751
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".git", ".next", ".turbo", "build", "dist", "node_modules"]);
|
|
@@ -5249,26 +5763,26 @@ function hash(value, length = 10) {
|
|
|
5249
5763
|
}
|
|
5250
5764
|
function safeStat(path) {
|
|
5251
5765
|
try {
|
|
5252
|
-
return
|
|
5766
|
+
return statSync2(path);
|
|
5253
5767
|
} catch {
|
|
5254
5768
|
return null;
|
|
5255
5769
|
}
|
|
5256
5770
|
}
|
|
5257
5771
|
function defaultRoots(input) {
|
|
5258
5772
|
return {
|
|
5259
|
-
agents: [
|
|
5260
|
-
claude: [
|
|
5261
|
-
codex: [
|
|
5773
|
+
agents: [join5(input.home, ".agents", "skills")],
|
|
5774
|
+
claude: [join5(input.home, ".claude", "skills"), join5(input.cwd, ".claude", "skills")],
|
|
5775
|
+
codex: [join5(input.home, ".codex", "skills"), join5(input.cwd, ".codex", "skills")],
|
|
5262
5776
|
opencode: [
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5777
|
+
join5(input.home, ".opencode", "skills"),
|
|
5778
|
+
join5(input.home, ".config", "opencode", "skills"),
|
|
5779
|
+
join5(input.home, "Library", "Application Support", "opencode", "skills"),
|
|
5780
|
+
join5(input.cwd, ".opencode", "skills")
|
|
5267
5781
|
],
|
|
5268
5782
|
workspace: [
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5783
|
+
join5(input.cwd, "skills"),
|
|
5784
|
+
join5(input.cwd, ".agents", "skills"),
|
|
5785
|
+
join5(input.cwd, ".orgx", "skills")
|
|
5272
5786
|
]
|
|
5273
5787
|
};
|
|
5274
5788
|
}
|
|
@@ -5290,7 +5804,7 @@ function walkSkillFiles(root, maxFiles = 200) {
|
|
|
5290
5804
|
}
|
|
5291
5805
|
for (const entry of entries) {
|
|
5292
5806
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
5293
|
-
const path =
|
|
5807
|
+
const path = join5(current, entry.name);
|
|
5294
5808
|
if (entry.isDirectory()) {
|
|
5295
5809
|
stack.push(path);
|
|
5296
5810
|
} else if (entry.isFile() && /\.(md|mdc|txt)$/i.test(entry.name)) {
|
|
@@ -5421,7 +5935,7 @@ function buildLocalSkillExtensionContent(candidates, context) {
|
|
|
5421
5935
|
"",
|
|
5422
5936
|
`## ${candidate.title}`,
|
|
5423
5937
|
"",
|
|
5424
|
-
`- Source: ${candidate.source} (${
|
|
5938
|
+
`- Source: ${candidate.source} (${relative(process.cwd(), candidate.path)})`,
|
|
5425
5939
|
`- Suggested agents: ${candidate.agentDomains.join(", ")}`,
|
|
5426
5940
|
`- Preserve: ${candidate.snippet || "local workflow preference from this skill file."}`
|
|
5427
5941
|
);
|
|
@@ -5697,7 +6211,7 @@ function initializeWizardSentry() {
|
|
|
5697
6211
|
Sentry.init({
|
|
5698
6212
|
dsn,
|
|
5699
6213
|
environment: process.env.ORGX_SENTRY_ENVIRONMENT || "production",
|
|
5700
|
-
release: "useorgx-wizard@0.1.
|
|
6214
|
+
release: "useorgx-wizard@0.1.56",
|
|
5701
6215
|
tracesSampleRate: sampleRate(process.env.ORGX_SENTRY_TRACES_SAMPLE_RATE),
|
|
5702
6216
|
enableLogs: true,
|
|
5703
6217
|
sendDefaultPii: false,
|
|
@@ -6415,8 +6929,8 @@ async function fetchOnboardingState(auth) {
|
|
|
6415
6929
|
}
|
|
6416
6930
|
|
|
6417
6931
|
// src/lib/ai-session-import.ts
|
|
6418
|
-
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as
|
|
6419
|
-
import { basename as basename3, join as
|
|
6932
|
+
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync3 } from "fs";
|
|
6933
|
+
import { basename as basename3, join as join6, relative as relative2 } from "path";
|
|
6420
6934
|
var AI_SESSION_SOURCES = ["codex", "claude"];
|
|
6421
6935
|
var DEFAULT_LIMIT_PER_SOURCE = 3;
|
|
6422
6936
|
var DEFAULT_SINCE_DAYS = 30;
|
|
@@ -6582,10 +7096,10 @@ function collectJsonlFiles(root, source) {
|
|
|
6582
7096
|
continue;
|
|
6583
7097
|
}
|
|
6584
7098
|
for (const entry of entries) {
|
|
6585
|
-
const path =
|
|
7099
|
+
const path = join6(current, entry);
|
|
6586
7100
|
let stats;
|
|
6587
7101
|
try {
|
|
6588
|
-
stats =
|
|
7102
|
+
stats = statSync3(path);
|
|
6589
7103
|
} catch {
|
|
6590
7104
|
continue;
|
|
6591
7105
|
}
|
|
@@ -6603,7 +7117,7 @@ function collectJsonlFiles(root, source) {
|
|
|
6603
7117
|
function readSessionImport(candidate, root, options) {
|
|
6604
7118
|
let stats;
|
|
6605
7119
|
try {
|
|
6606
|
-
stats =
|
|
7120
|
+
stats = statSync3(candidate.path);
|
|
6607
7121
|
} catch {
|
|
6608
7122
|
return null;
|
|
6609
7123
|
}
|
|
@@ -6621,7 +7135,7 @@ function readSessionImport(candidate, root, options) {
|
|
|
6621
7135
|
}
|
|
6622
7136
|
const deduped = [...new Set(relevantLines)].slice(0, 80);
|
|
6623
7137
|
if (deduped.length === 0) return null;
|
|
6624
|
-
const relativePath =
|
|
7138
|
+
const relativePath = relative2(root, candidate.path);
|
|
6625
7139
|
return {
|
|
6626
7140
|
import: {
|
|
6627
7141
|
sourceId: `${candidate.source}:${basename3(candidate.path, ".jsonl")}`,
|
|
@@ -6696,9 +7210,9 @@ function loadAiSessionImports(options) {
|
|
|
6696
7210
|
// src/lib/work-graph-source-adapters.ts
|
|
6697
7211
|
import { createHash as createHash4 } from "crypto";
|
|
6698
7212
|
import { execFileSync } from "child_process";
|
|
6699
|
-
import { closeSync, existsSync as existsSync7, openSync, readFileSync as readFileSync5, readdirSync as readdirSync5, readSync, statSync as
|
|
7213
|
+
import { closeSync, existsSync as existsSync7, openSync, readFileSync as readFileSync5, readdirSync as readdirSync5, readSync, statSync as statSync4 } from "fs";
|
|
6700
7214
|
import { homedir as homedir2 } from "os";
|
|
6701
|
-
import { basename as basename4, join as
|
|
7215
|
+
import { basename as basename4, join as join7, resolve } from "path";
|
|
6702
7216
|
var CLIENT_SOURCES = ["claude_code", "codex", "opencode", "goose", "cursor", "github", "slack"];
|
|
6703
7217
|
var DEFAULT_LIMIT_PER_SOURCE2 = 8;
|
|
6704
7218
|
var DEFAULT_SINCE_DAYS2 = 45;
|
|
@@ -6725,7 +7239,7 @@ function expandPath(path, env) {
|
|
|
6725
7239
|
}
|
|
6726
7240
|
function safeStat2(path) {
|
|
6727
7241
|
try {
|
|
6728
|
-
return
|
|
7242
|
+
return statSync4(path);
|
|
6729
7243
|
} catch {
|
|
6730
7244
|
return null;
|
|
6731
7245
|
}
|
|
@@ -6746,7 +7260,7 @@ function walkFiles(root, predicate, maxFiles = 500) {
|
|
|
6746
7260
|
}
|
|
6747
7261
|
for (const entry of entries) {
|
|
6748
7262
|
if (ignored.has(entry)) continue;
|
|
6749
|
-
const path =
|
|
7263
|
+
const path = join7(current, entry);
|
|
6750
7264
|
const stats = safeStat2(path);
|
|
6751
7265
|
if (!stats) continue;
|
|
6752
7266
|
if (stats.isDirectory()) {
|
|
@@ -8078,11 +8592,138 @@ Rollback: ${plan.recommended_follow_up.rollback}`,
|
|
|
8078
8592
|
);
|
|
8079
8593
|
}
|
|
8080
8594
|
|
|
8595
|
+
// src/lib/operating-map.ts
|
|
8596
|
+
import { createHash as createHash6 } from "crypto";
|
|
8597
|
+
function parseResponseBody6(text2) {
|
|
8598
|
+
if (!text2) return null;
|
|
8599
|
+
try {
|
|
8600
|
+
return JSON.parse(text2);
|
|
8601
|
+
} catch {
|
|
8602
|
+
return text2;
|
|
8603
|
+
}
|
|
8604
|
+
}
|
|
8605
|
+
function formatHttpError5(status, body) {
|
|
8606
|
+
if (typeof body === "string" && body.trim()) return `HTTP ${status}: ${body}`;
|
|
8607
|
+
if (isRecord(body) && isRecord(body.error)) {
|
|
8608
|
+
const code = typeof body.error.code === "string" ? body.error.code : "api_error";
|
|
8609
|
+
const message = typeof body.error.message === "string" ? body.error.message : `HTTP ${status}`;
|
|
8610
|
+
return `HTTP ${status} ${code}: ${message}`;
|
|
8611
|
+
}
|
|
8612
|
+
return `HTTP ${status}`;
|
|
8613
|
+
}
|
|
8614
|
+
function extractData(payload) {
|
|
8615
|
+
return isRecord(payload) && "data" in payload ? payload.data : payload;
|
|
8616
|
+
}
|
|
8617
|
+
function parseDiscoveryResult(payload) {
|
|
8618
|
+
const data = extractData(payload);
|
|
8619
|
+
if (!isRecord(data) || !isRecord(data.run) || !Array.isArray(data.processCards)) {
|
|
8620
|
+
throw new Error("OrgX returned an incomplete operating-map discovery payload.");
|
|
8621
|
+
}
|
|
8622
|
+
const run = data.run;
|
|
8623
|
+
if (typeof run.id !== "string" || typeof run.mode !== "string" || typeof run.status !== "string") {
|
|
8624
|
+
throw new Error("OrgX returned an invalid operating-map discovery run.");
|
|
8625
|
+
}
|
|
8626
|
+
return {
|
|
8627
|
+
run: {
|
|
8628
|
+
id: run.id,
|
|
8629
|
+
mode: run.mode,
|
|
8630
|
+
status: run.status,
|
|
8631
|
+
query: typeof run.query === "string" ? run.query : null,
|
|
8632
|
+
observationCount: typeof run.observationCount === "number" ? run.observationCount : 0,
|
|
8633
|
+
candidateProcessCardCount: typeof run.candidateProcessCardCount === "number" ? run.candidateProcessCardCount : data.processCards.length,
|
|
8634
|
+
citationCount: typeof run.citationCount === "number" ? run.citationCount : 0,
|
|
8635
|
+
sourceHealth: Array.isArray(run.sourceHealth) ? run.sourceHealth : [],
|
|
8636
|
+
limitations: Array.isArray(run.limitations) ? run.limitations.filter((item) => typeof item === "string") : []
|
|
8637
|
+
},
|
|
8638
|
+
observations: Array.isArray(data.observations) ? data.observations.filter(isRecord) : [],
|
|
8639
|
+
processCards: data.processCards.filter(isRecord).map((card) => {
|
|
8640
|
+
const ref = isRecord(card.processCandidateRef) ? card.processCandidateRef : {};
|
|
8641
|
+
return {
|
|
8642
|
+
processCandidateRef: {
|
|
8643
|
+
id: typeof ref.id === "string" ? ref.id : "",
|
|
8644
|
+
workspaceId: typeof ref.workspaceId === "string" ? ref.workspaceId : ""
|
|
8645
|
+
},
|
|
8646
|
+
displayName: typeof card.displayName === "string" ? card.displayName : "Unnamed workflow",
|
|
8647
|
+
confidence: typeof card.confidence === "number" ? card.confidence : 0,
|
|
8648
|
+
nextConfirmationQuestion: typeof card.nextConfirmationQuestion === "string" ? card.nextConfirmationQuestion : null,
|
|
8649
|
+
candidateTrigger: isRecord(card.candidateTrigger) ? card.candidateTrigger : {},
|
|
8650
|
+
handoffDelays: Array.isArray(card.handoffDelays) ? card.handoffDelays.filter(isRecord).map((handoff) => ({
|
|
8651
|
+
from: typeof handoff.from === "string" ? handoff.from : "unknown",
|
|
8652
|
+
to: typeof handoff.to === "string" ? handoff.to : "unknown",
|
|
8653
|
+
delayMinutes: typeof handoff.delayMinutes === "number" ? handoff.delayMinutes : null
|
|
8654
|
+
})) : [],
|
|
8655
|
+
riskFlags: Array.isArray(card.riskFlags) ? card.riskFlags.filter((item) => typeof item === "string") : []
|
|
8656
|
+
};
|
|
8657
|
+
}),
|
|
8658
|
+
confirmedProcessRefs: Array.isArray(data.confirmedProcessRefs) ? data.confirmedProcessRefs.filter(isRecord).flatMap(
|
|
8659
|
+
(ref) => typeof ref.id === "string" && typeof ref.workspaceId === "string" ? [{ id: ref.id, workspaceId: ref.workspaceId }] : []
|
|
8660
|
+
) : []
|
|
8661
|
+
};
|
|
8662
|
+
}
|
|
8663
|
+
async function requireOrgxAuth4(options = {}) {
|
|
8664
|
+
const auth = await resolveOrgxAuth(options);
|
|
8665
|
+
if (!auth) {
|
|
8666
|
+
throw new Error("No OrgX API key configured. Run `wizard auth login` or set ORGX_API_KEY first.");
|
|
8667
|
+
}
|
|
8668
|
+
return auth;
|
|
8669
|
+
}
|
|
8670
|
+
function defaultOperatingMapIdempotencyKey(input) {
|
|
8671
|
+
const digest = createHash6("sha256").update(JSON.stringify(input)).digest("hex").slice(0, 32);
|
|
8672
|
+
return `wizard:operating-map:${input.workspaceId}:${digest}`;
|
|
8673
|
+
}
|
|
8674
|
+
async function startOperatingMapDiscovery(input, options = {}) {
|
|
8675
|
+
const auth = await requireOrgxAuth4(options);
|
|
8676
|
+
const response = await fetchWithRetry(buildOrgxApiUrl("/v1/discovery-runs", auth.baseUrl), {
|
|
8677
|
+
method: "POST",
|
|
8678
|
+
headers: {
|
|
8679
|
+
Authorization: `Bearer ${auth.apiKey}`,
|
|
8680
|
+
"Content-Type": "application/json",
|
|
8681
|
+
"Idempotency-Key": input.idempotencyKey
|
|
8682
|
+
},
|
|
8683
|
+
body: JSON.stringify({
|
|
8684
|
+
workspace_id: input.workspaceId,
|
|
8685
|
+
mode: input.mode ?? "bounded_sync",
|
|
8686
|
+
query: input.query ?? null,
|
|
8687
|
+
source_kinds: input.sourceKinds ?? []
|
|
8688
|
+
})
|
|
8689
|
+
});
|
|
8690
|
+
const body = parseResponseBody6(await response.text());
|
|
8691
|
+
if (!response.ok) {
|
|
8692
|
+
throw new Error(`Unable to start the operating-map discovery run. ${formatHttpError5(response.status, body)}`);
|
|
8693
|
+
}
|
|
8694
|
+
const result = parseDiscoveryResult(body);
|
|
8695
|
+
const meta = isRecord(body) && isRecord(body.meta) ? body.meta : {};
|
|
8696
|
+
return { result, duplicate: meta.duplicate === true };
|
|
8697
|
+
}
|
|
8698
|
+
async function proposeOperatingProcessFromMap(input, options = {}) {
|
|
8699
|
+
const auth = await requireOrgxAuth4(options);
|
|
8700
|
+
const response = await fetchWithRetry(
|
|
8701
|
+
buildOrgxApiUrl(`/v1/discovery-runs/${encodeURIComponent(input.discoveryRunId)}/propose`, auth.baseUrl),
|
|
8702
|
+
{
|
|
8703
|
+
method: "POST",
|
|
8704
|
+
headers: {
|
|
8705
|
+
Authorization: `Bearer ${auth.apiKey}`,
|
|
8706
|
+
"Content-Type": "application/json",
|
|
8707
|
+
"Idempotency-Key": input.idempotencyKey
|
|
8708
|
+
},
|
|
8709
|
+
body: JSON.stringify({
|
|
8710
|
+
workspace_id: input.workspaceId,
|
|
8711
|
+
process_candidate_id: input.processCandidateId
|
|
8712
|
+
})
|
|
8713
|
+
}
|
|
8714
|
+
);
|
|
8715
|
+
const body = parseResponseBody6(await response.text());
|
|
8716
|
+
if (!response.ok) {
|
|
8717
|
+
throw new Error(`Unable to propose the OperatingProcess. ${formatHttpError5(response.status, body)}`);
|
|
8718
|
+
}
|
|
8719
|
+
return extractData(body);
|
|
8720
|
+
}
|
|
8721
|
+
|
|
8081
8722
|
// src/lib/work-graph.ts
|
|
8082
|
-
import { createHash as
|
|
8723
|
+
import { createHash as createHash8 } from "crypto";
|
|
8083
8724
|
|
|
8084
8725
|
// src/lib/work-graph-investigation.ts
|
|
8085
|
-
import { createHash as
|
|
8726
|
+
import { createHash as createHash7 } from "crypto";
|
|
8086
8727
|
var WORK_GRAPH_INVESTIGATION_SCHEMA_VERSION = "2.0.0";
|
|
8087
8728
|
var WORK_GRAPH_INVESTIGATION_CLIENTS = [
|
|
8088
8729
|
"claude_code",
|
|
@@ -8215,7 +8856,7 @@ var CAPABILITY_CEILINGS = {
|
|
|
8215
8856
|
}
|
|
8216
8857
|
};
|
|
8217
8858
|
function hash3(value, length = 16) {
|
|
8218
|
-
return
|
|
8859
|
+
return createHash7("sha256").update(JSON.stringify(value)).digest("hex").slice(0, length);
|
|
8219
8860
|
}
|
|
8220
8861
|
function clamp(value, min = 0, max = 1) {
|
|
8221
8862
|
return Math.max(min, Math.min(max, value));
|
|
@@ -9317,7 +9958,7 @@ function clampScore2(value) {
|
|
|
9317
9958
|
return Math.max(0, Math.min(100, Math.round(value)));
|
|
9318
9959
|
}
|
|
9319
9960
|
function hashJson(value) {
|
|
9320
|
-
return
|
|
9961
|
+
return createHash8("sha256").update(JSON.stringify(value)).digest("hex");
|
|
9321
9962
|
}
|
|
9322
9963
|
function normalizeFingerprintText(value) {
|
|
9323
9964
|
return value.toLowerCase().replace(/https?:\/\/\S+/g, "url").replace(/[0-9a-f]{12,}/g, "hash").replace(/\b[0-9a-f]{8}-[0-9a-f-]{27,}\b/g, "uuid").replace(/\s+/g, " ").trim().slice(0, 600);
|
|
@@ -12529,14 +13170,14 @@ function renderAqAgentBrief(report, links = {}) {
|
|
|
12529
13170
|
}
|
|
12530
13171
|
|
|
12531
13172
|
// src/lib/work-graph-publish.ts
|
|
12532
|
-
import { createHash as
|
|
13173
|
+
import { createHash as createHash9, randomUUID as randomUUID2 } from "crypto";
|
|
12533
13174
|
import { gzipSync } from "zlib";
|
|
12534
13175
|
var WORK_GRAPH_REPORT_GZIP_THRESHOLD_BYTES = 4e6;
|
|
12535
13176
|
var WORK_GRAPH_REPORT_CHUNK_UPLOAD_THRESHOLD_BYTES = 5e5;
|
|
12536
13177
|
var WORK_GRAPH_REPORT_CHUNK_CHARS = 3e4;
|
|
12537
13178
|
var WORK_GRAPH_REPORT_CHUNK_UPLOAD_TIMEOUT_MS = 3e5;
|
|
12538
13179
|
function hashText(value) {
|
|
12539
|
-
return
|
|
13180
|
+
return createHash9("sha256").update(value).digest("hex");
|
|
12540
13181
|
}
|
|
12541
13182
|
function buildWorkGraphReportPostPayload(report, options = {}) {
|
|
12542
13183
|
return {
|
|
@@ -12743,7 +13384,7 @@ async function publishWorkGraphEvents(fingerprint, patch, options = {}) {
|
|
|
12743
13384
|
}
|
|
12744
13385
|
|
|
12745
13386
|
// src/lib/work-graph-hook-events.ts
|
|
12746
|
-
import { createHash as
|
|
13387
|
+
import { createHash as createHash10 } from "crypto";
|
|
12747
13388
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
12748
13389
|
var SOURCE_CLIENTS = [
|
|
12749
13390
|
"codex",
|
|
@@ -12778,7 +13419,7 @@ function asStringArray(value) {
|
|
|
12778
13419
|
return value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
12779
13420
|
}
|
|
12780
13421
|
function stableHash(value) {
|
|
12781
|
-
return
|
|
13422
|
+
return createHash10("sha256").update(value).digest("hex").slice(0, 20);
|
|
12782
13423
|
}
|
|
12783
13424
|
function normalizeSourceClient2(value) {
|
|
12784
13425
|
const raw = asString2(value)?.toLowerCase();
|
|
@@ -12982,22 +13623,22 @@ function buildWorkGraphHookReplayPatch(readResult) {
|
|
|
12982
13623
|
}
|
|
12983
13624
|
|
|
12984
13625
|
// src/lib/runtime-hooks.ts
|
|
12985
|
-
import { copyFileSync, existsSync as existsSync9, mkdirSync as
|
|
13626
|
+
import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
|
|
12986
13627
|
import { homedir as homedir3 } from "os";
|
|
12987
|
-
import { dirname as
|
|
13628
|
+
import { dirname as dirname5, join as join8 } from "path";
|
|
12988
13629
|
var HOOK_MARKER = "orgx-session-hook.mjs";
|
|
12989
13630
|
var EMIT_HOOK_MARKER = "orgx-emit-execution-graph.mjs";
|
|
12990
13631
|
var HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PermissionRequest", "Stop"];
|
|
12991
13632
|
var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "SubagentStop", "Stop", "SessionEnd"];
|
|
12992
13633
|
function defaultPaths(options = {}) {
|
|
12993
|
-
const hookDir =
|
|
13634
|
+
const hookDir = join8(ORGX_WIZARD_CONFIG_HOME, "hooks");
|
|
12994
13635
|
return {
|
|
12995
|
-
claudeSettingsPath: options.claudeSettingsPath ??
|
|
12996
|
-
codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ??
|
|
12997
|
-
codexHooksPath: options.codexHooksPath ??
|
|
12998
|
-
hookScriptPath: options.hookScriptPath ??
|
|
12999
|
-
emitHookScriptPath: options.emitHookScriptPath ??
|
|
13000
|
-
outboxPath: options.outboxPath ??
|
|
13636
|
+
claudeSettingsPath: options.claudeSettingsPath ?? join8(CLAUDE_DIR, "settings.json"),
|
|
13637
|
+
codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join8(CODEX_DIR, "config.toml"),
|
|
13638
|
+
codexHooksPath: options.codexHooksPath ?? join8(CODEX_DIR, "hooks.json"),
|
|
13639
|
+
hookScriptPath: options.hookScriptPath ?? join8(hookDir, HOOK_MARKER),
|
|
13640
|
+
emitHookScriptPath: options.emitHookScriptPath ?? join8(hookDir, EMIT_HOOK_MARKER),
|
|
13641
|
+
outboxPath: options.outboxPath ?? join8(hookDir, "events.jsonl")
|
|
13001
13642
|
};
|
|
13002
13643
|
}
|
|
13003
13644
|
function countJsonlLines(path) {
|
|
@@ -13379,7 +14020,7 @@ function installRuntimeHooks(targets, options = {}) {
|
|
|
13379
14020
|
hookScript: false,
|
|
13380
14021
|
emitHookScript: false
|
|
13381
14022
|
};
|
|
13382
|
-
|
|
14023
|
+
mkdirSync4(dirname5(paths.hookScriptPath), { recursive: true, mode: 448 });
|
|
13383
14024
|
const scriptContent = buildRuntimeHookScriptContent();
|
|
13384
14025
|
if (readTextIfExists(paths.hookScriptPath) !== scriptContent) {
|
|
13385
14026
|
const backup = backupExisting(paths.hookScriptPath, now);
|
|
@@ -13387,7 +14028,7 @@ function installRuntimeHooks(targets, options = {}) {
|
|
|
13387
14028
|
writeTextFile(paths.hookScriptPath, scriptContent, { mode: 448 });
|
|
13388
14029
|
changed.hookScript = true;
|
|
13389
14030
|
}
|
|
13390
|
-
|
|
14031
|
+
mkdirSync4(dirname5(paths.emitHookScriptPath), { recursive: true, mode: 448 });
|
|
13391
14032
|
const emitScriptContent = buildExecutionGraphEmitScriptContent();
|
|
13392
14033
|
if (readTextIfExists(paths.emitHookScriptPath) !== emitScriptContent) {
|
|
13393
14034
|
const backup = backupExisting(paths.emitHookScriptPath, now);
|
|
@@ -14013,6 +14654,73 @@ async function requestWorkloadDiagnosis(input, options = {}) {
|
|
|
14013
14654
|
return parsed.data;
|
|
14014
14655
|
}
|
|
14015
14656
|
|
|
14657
|
+
// src/lib/deepseek-launcher.ts
|
|
14658
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
14659
|
+
async function resolveFreshMcpAuth(deps) {
|
|
14660
|
+
const authPath = deps.authPath ?? ORGX_WIZARD_AUTH_PATH;
|
|
14661
|
+
const readAuth = deps.readAuth ?? readWizardAuth;
|
|
14662
|
+
const stored = await readAuth(authPath);
|
|
14663
|
+
if (!stored) {
|
|
14664
|
+
throw new Error("OrgX is not paired. Run orgx-wizard auth login first.");
|
|
14665
|
+
}
|
|
14666
|
+
if (stored.source !== "pkce") return stored;
|
|
14667
|
+
if (!stored.refreshToken || !stored.oauthClientId) {
|
|
14668
|
+
throw new Error("OrgX browser authorization cannot be refreshed. Run orgx-wizard auth login again.");
|
|
14669
|
+
}
|
|
14670
|
+
const refresh = deps.refreshToken ?? refreshAccessToken;
|
|
14671
|
+
let refreshed;
|
|
14672
|
+
try {
|
|
14673
|
+
refreshed = await refresh({
|
|
14674
|
+
refreshToken: stored.refreshToken,
|
|
14675
|
+
clientId: stored.oauthClientId
|
|
14676
|
+
});
|
|
14677
|
+
} catch (error) {
|
|
14678
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
14679
|
+
throw new Error(`OrgX authorization refresh failed. Run orgx-wizard auth login again. ${detail}`);
|
|
14680
|
+
}
|
|
14681
|
+
const writeAuth = deps.writeAuth ?? writeWizardAuth;
|
|
14682
|
+
return writeAuth(
|
|
14683
|
+
{
|
|
14684
|
+
apiKey: refreshed.access_token,
|
|
14685
|
+
baseUrl: stored.baseUrl,
|
|
14686
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14687
|
+
source: "pkce",
|
|
14688
|
+
refreshToken: refreshed.refresh_token ?? stored.refreshToken,
|
|
14689
|
+
oauthClientId: stored.oauthClientId
|
|
14690
|
+
},
|
|
14691
|
+
authPath
|
|
14692
|
+
);
|
|
14693
|
+
}
|
|
14694
|
+
async function launchDeepseekWithOrgx(prompt, deps = {}) {
|
|
14695
|
+
if (prompt.length === 0 || prompt.every((part) => !part.trim())) {
|
|
14696
|
+
throw new Error('Give DeepSeek a prompt, for example: orgx-wizard deepseek "What changed while I was away?"');
|
|
14697
|
+
}
|
|
14698
|
+
const runtime = inspectDeepseekRuntime(deps.runtimeRunner);
|
|
14699
|
+
if (!runtime.installed) {
|
|
14700
|
+
throw new Error("DeepSeek Harness was not found. Run orgx-wizard setup after installing DSH.");
|
|
14701
|
+
}
|
|
14702
|
+
if (!runtime.supported) {
|
|
14703
|
+
throw new Error(`DeepSeek Harness ${runtime.version ?? "unknown"} is not supported by this OrgX plugin.`);
|
|
14704
|
+
}
|
|
14705
|
+
const auth = await resolveFreshMcpAuth(deps);
|
|
14706
|
+
const childEnv = {
|
|
14707
|
+
...deps.env ?? process.env,
|
|
14708
|
+
ORGX_MCP_ACCESS_TOKEN: auth.apiKey
|
|
14709
|
+
};
|
|
14710
|
+
delete childEnv.ORGX_API_KEY;
|
|
14711
|
+
const spawn2 = deps.spawn ?? spawnSync4;
|
|
14712
|
+
const result = spawn2(
|
|
14713
|
+
"dsh",
|
|
14714
|
+
["--profile", DEEPSEEK_PROFILE, prompt.join(" ")],
|
|
14715
|
+
{
|
|
14716
|
+
env: childEnv,
|
|
14717
|
+
stdio: "inherit"
|
|
14718
|
+
}
|
|
14719
|
+
);
|
|
14720
|
+
if (result.error) throw result.error;
|
|
14721
|
+
return { status: result.status ?? 1 };
|
|
14722
|
+
}
|
|
14723
|
+
|
|
14016
14724
|
// src/cli.ts
|
|
14017
14725
|
var ICON = {
|
|
14018
14726
|
ok: pc3.green("\u2713"),
|
|
@@ -14082,7 +14790,7 @@ function printSurfaceSummary(results) {
|
|
|
14082
14790
|
` ${ICON.skip} ${pc3.dim("No supported AI tools detected on this machine.")}`
|
|
14083
14791
|
);
|
|
14084
14792
|
console.log(
|
|
14085
|
-
` ${pc3.dim("\u2192")} ${pc3.dim("Install Claude, Cursor, Codex, VS Code, Windsurf, or Zed, then re-run setup.")}`
|
|
14793
|
+
` ${pc3.dim("\u2192")} ${pc3.dim("Install Claude, Cursor, Codex, DeepSeek Harness, VS Code, Windsurf, or Zed, then re-run setup.")}`
|
|
14086
14794
|
);
|
|
14087
14795
|
return;
|
|
14088
14796
|
}
|
|
@@ -14450,6 +15158,86 @@ async function runAuditCommand(options) {
|
|
|
14450
15158
|
console.log(` ${ICON.ok} ${pc3.green("follow-up ")} ${pc3.bold(followUp.title)} ${pc3.dim(followUp.id)}`);
|
|
14451
15159
|
}
|
|
14452
15160
|
}
|
|
15161
|
+
async function runOperatingMapCommand(queryParts, options) {
|
|
15162
|
+
const auth = await resolveOrgxAuth();
|
|
15163
|
+
if (!auth) {
|
|
15164
|
+
throw new Error("Operating-map discovery requires OrgX auth. Run `wizard auth login` first.");
|
|
15165
|
+
}
|
|
15166
|
+
const workspace = options.workspaceId?.trim() ? { id: options.workspaceId.trim(), name: options.workspaceId.trim() } : await getCurrentWorkspace();
|
|
15167
|
+
if (!workspace) {
|
|
15168
|
+
throw new Error("No current OrgX workspace found. Run `wizard workspace create <name>` first.");
|
|
15169
|
+
}
|
|
15170
|
+
const query = queryParts.join(" ").trim() || null;
|
|
15171
|
+
const mode = options.deepSearch ? "deep_search" : "bounded_sync";
|
|
15172
|
+
const sourceKinds = (options.source ?? "").split(",").map((source) => source.trim()).filter(Boolean);
|
|
15173
|
+
const idempotencyKey = options.idempotencyKey?.trim() || defaultOperatingMapIdempotencyKey({
|
|
15174
|
+
workspaceId: workspace.id,
|
|
15175
|
+
mode,
|
|
15176
|
+
query,
|
|
15177
|
+
sourceKinds
|
|
15178
|
+
});
|
|
15179
|
+
const spinner = createOrgxSpinner(mode === "deep_search" ? "Mapping workflows with cited deep search" : "Mapping observed workflows");
|
|
15180
|
+
spinner.start();
|
|
15181
|
+
const discovery = await startOperatingMapDiscovery({
|
|
15182
|
+
workspaceId: workspace.id,
|
|
15183
|
+
mode,
|
|
15184
|
+
query,
|
|
15185
|
+
sourceKinds,
|
|
15186
|
+
idempotencyKey
|
|
15187
|
+
});
|
|
15188
|
+
spinner.succeed(discovery.duplicate ? "Replayed the existing operating-map discovery" : "Operating-map discovery complete");
|
|
15189
|
+
const payload = {
|
|
15190
|
+
workspaceId: workspace.id,
|
|
15191
|
+
idempotencyKey,
|
|
15192
|
+
duplicate: discovery.duplicate,
|
|
15193
|
+
run: discovery.result.run,
|
|
15194
|
+
processCards: discovery.result.processCards
|
|
15195
|
+
};
|
|
15196
|
+
if (options.json) {
|
|
15197
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
15198
|
+
} else {
|
|
15199
|
+
console.log(` ${ICON.ok} ${pc3.green("observations ")} ${pc3.dim(String(discovery.result.run.observationCount))}`);
|
|
15200
|
+
console.log(` ${ICON.ok} ${pc3.green("candidates ")} ${pc3.dim(String(discovery.result.processCards.length))}`);
|
|
15201
|
+
console.log(` ${ICON.ok} ${pc3.green("citations ")} ${pc3.dim(String(discovery.result.run.citationCount))}`);
|
|
15202
|
+
for (const [index, card] of discovery.result.processCards.entries()) {
|
|
15203
|
+
console.log("");
|
|
15204
|
+
console.log(` ${pc3.bold(`${index + 1}. ${card.displayName}`)} ${pc3.dim(`${Math.round(card.confidence * 100)}% confidence \xB7 ${card.processCandidateRef.id}`)}`);
|
|
15205
|
+
if (card.nextConfirmationQuestion) console.log(` ${pc3.yellow("confirm:")} ${card.nextConfirmationQuestion}`);
|
|
15206
|
+
if (card.riskFlags.length > 0) console.log(` ${pc3.yellow("limits:")} ${card.riskFlags.join("; ")}`);
|
|
15207
|
+
}
|
|
15208
|
+
if (discovery.result.run.limitations.length > 0) {
|
|
15209
|
+
console.log("");
|
|
15210
|
+
console.log(` ${pc3.yellow("limitations:")} ${discovery.result.run.limitations.join("; ")}`);
|
|
15211
|
+
}
|
|
15212
|
+
}
|
|
15213
|
+
const candidate = options.candidate?.trim();
|
|
15214
|
+
if (!candidate) return;
|
|
15215
|
+
const selected = /^\d+$/.test(candidate) ? discovery.result.processCards[Number(candidate) - 1] : discovery.result.processCards.find((card) => card.processCandidateRef.id === candidate);
|
|
15216
|
+
if (!selected?.processCandidateRef.id) {
|
|
15217
|
+
throw new Error(`Process candidate ${candidate} was not found in discovery run ${discovery.result.run.id}.`);
|
|
15218
|
+
}
|
|
15219
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
15220
|
+
if (!options.yes) {
|
|
15221
|
+
if (!interactive) throw new Error("Proposing an OperatingProcess requires --yes in non-interactive mode.");
|
|
15222
|
+
const confirmed = await clack.confirm({
|
|
15223
|
+
message: `Propose \u201C${selected.displayName}\u201D as an OperatingProcess (still requires human confirmation)?`,
|
|
15224
|
+
initialValue: false
|
|
15225
|
+
});
|
|
15226
|
+
if (clack.isCancel(confirmed) || !confirmed) return;
|
|
15227
|
+
}
|
|
15228
|
+
const proposal = await proposeOperatingProcessFromMap({
|
|
15229
|
+
workspaceId: workspace.id,
|
|
15230
|
+
discoveryRunId: discovery.result.run.id,
|
|
15231
|
+
processCandidateId: selected.processCandidateRef.id,
|
|
15232
|
+
idempotencyKey: `wizard:operating-process:${discovery.result.run.id}:${selected.processCandidateRef.id}`
|
|
15233
|
+
});
|
|
15234
|
+
if (options.json) {
|
|
15235
|
+
console.log(JSON.stringify({ ...payload, proposal }, null, 2));
|
|
15236
|
+
} else {
|
|
15237
|
+
console.log(` ${ICON.ok} ${pc3.green("proposal ")} ${pc3.dim(selected.displayName)}`);
|
|
15238
|
+
console.log(` ${pc3.dim("Next step ")} Review and confirm the OperatingProcess in OrgX; the wizard never auto-activates inferred workflow ownership.`);
|
|
15239
|
+
}
|
|
15240
|
+
}
|
|
14453
15241
|
function runWorkGraphExtractionSchemaCommand(options) {
|
|
14454
15242
|
const protocol = buildWorkGraphExtractionProtocol();
|
|
14455
15243
|
const outputPath = options.output?.trim() ? resolve3(options.output.trim()) : "";
|
|
@@ -14749,7 +15537,7 @@ function openPathInEditor(path) {
|
|
|
14749
15537
|
if (!editor) {
|
|
14750
15538
|
return false;
|
|
14751
15539
|
}
|
|
14752
|
-
const result =
|
|
15540
|
+
const result = spawnSync5(editor, [path], {
|
|
14753
15541
|
shell: true,
|
|
14754
15542
|
stdio: "inherit"
|
|
14755
15543
|
});
|
|
@@ -15567,14 +16355,20 @@ async function promptOptionalCompanionPluginTargets(input) {
|
|
|
15567
16355
|
return selection;
|
|
15568
16356
|
}
|
|
15569
16357
|
function printPluginSkillOwnershipNote(targets) {
|
|
15570
|
-
if (
|
|
15571
|
-
|
|
16358
|
+
if (targets.includes("claude")) {
|
|
16359
|
+
console.log(
|
|
16360
|
+
` ${ICON.skip} ${pc3.dim(
|
|
16361
|
+
"The Claude Code plugin carries static OrgX skills and commands plus a focused, non-destructive, closed-world OrgX status profile through native OAuth. It installs no runtime hooks or transcript/context sync code."
|
|
16362
|
+
)}`
|
|
16363
|
+
);
|
|
16364
|
+
}
|
|
16365
|
+
if (targets.some((target) => target === "cursor" || target === "codex")) {
|
|
16366
|
+
console.log(
|
|
16367
|
+
` ${ICON.skip} ${pc3.dim(
|
|
16368
|
+
"Cursor and Codex companion plugins carry their own OrgX assets. Use 'wizard skills add' only for standalone rules or skills when those plugins are not in play."
|
|
16369
|
+
)}`
|
|
16370
|
+
);
|
|
15572
16371
|
}
|
|
15573
|
-
console.log(
|
|
15574
|
-
` ${ICON.skip} ${pc3.dim(
|
|
15575
|
-
"Cursor, Claude Code, and Codex companion plugins carry their own OrgX skills, rules, MCP config, commands, hooks, and agent prompts. Use 'wizard skills add' only for standalone rules or skills when those plugins are not in play."
|
|
15576
|
-
)}`
|
|
15577
|
-
);
|
|
15578
16372
|
}
|
|
15579
16373
|
async function installSelectedCompanionPlugins(input) {
|
|
15580
16374
|
if (input.targets.length === 0) {
|
|
@@ -15732,7 +16526,7 @@ async function main() {
|
|
|
15732
16526
|
initializeWizardSentry();
|
|
15733
16527
|
const program = new Command();
|
|
15734
16528
|
program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
|
|
15735
|
-
const pkgVersion = true ? "0.1.
|
|
16529
|
+
const pkgVersion = true ? "0.1.56" : void 0;
|
|
15736
16530
|
program.version(pkgVersion ?? "unknown", "-V, --version");
|
|
15737
16531
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
15738
16532
|
if (Boolean(actionCommand.optsWithGlobals().json)) return;
|
|
@@ -16035,6 +16829,10 @@ async function main() {
|
|
|
16035
16829
|
}
|
|
16036
16830
|
}
|
|
16037
16831
|
});
|
|
16832
|
+
program.command("deepseek").description("Run the pinned DeepSeek Harness profile with refreshed OrgX authorization.").argument("<prompt...>", "prompt to run in the DeepSeek Harness headless profile").action(async (prompt) => {
|
|
16833
|
+
const result = await launchDeepseekWithOrgx(prompt);
|
|
16834
|
+
if (result.status !== 0) process.exitCode = result.status;
|
|
16835
|
+
});
|
|
16038
16836
|
async function runPkceLogin(opts = {}) {
|
|
16039
16837
|
const spinner = createOrgxSpinner("Starting OrgX OAuth login");
|
|
16040
16838
|
spinner.start();
|
|
@@ -16449,6 +17247,15 @@ async function main() {
|
|
|
16449
17247
|
});
|
|
16450
17248
|
await runAuditCommand(options);
|
|
16451
17249
|
});
|
|
17250
|
+
program.command("map").alias("discovery").description("Map observed company workflows into evidence-gated OperatingProcess candidates.").argument("[query...]", "workflow, handoff, or system-of-record question for discovery/deep search").option("--deep-search", "query cited external research in addition to connected repository signals").option("--source <kinds>", "comma-separated source kinds to report and constrain (for example github,notion,slack)").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace").option("--candidate <id-or-number>", "propose one returned ProcessCard by id or 1-based display number").option("--idempotency-key <key>", "stable retry key; defaults to a hash of workspace, mode, query, and sources").option("--yes", "approve the explicit proposal in non-interactive mode").option("--json", "emit machine-readable discovery/proposal output").action(async (queryParts, options) => {
|
|
17251
|
+
await safeTrackWizardTelemetry("operating_map_started", {
|
|
17252
|
+
command: "map",
|
|
17253
|
+
deep_search: Boolean(options.deepSearch),
|
|
17254
|
+
has_candidate: Boolean(options.candidate),
|
|
17255
|
+
json: Boolean(options.json)
|
|
17256
|
+
});
|
|
17257
|
+
await runOperatingMapCommand(queryParts, options);
|
|
17258
|
+
});
|
|
16452
17259
|
const workGraph = program.command("work-graph").description("Run AQ from real AI-work receipts and surface the first repair that raises execution capacity.");
|
|
16453
17260
|
workGraph.command("extraction-schema").description("Print the packaged AI-client audit skill used to search sessions, messages, tools, domains, and logs.").option("--output <path>", "write the schema prompt to a file").option("--json", "emit the protocol as JSON instead of Markdown").action(async (options) => {
|
|
16454
17261
|
await safeTrackWizardTelemetry("work_graph_extraction_schema_started", {
|
|
@@ -16757,4 +17564,4 @@ main().catch(async (error) => {
|
|
|
16757
17564
|
process.exitCode = 1;
|
|
16758
17565
|
});
|
|
16759
17566
|
//# sourceMappingURL=cli.js.map
|
|
16760
|
-
//# debugId=
|
|
17567
|
+
//# debugId=02842523-d681-5cea-96aa-0f0c896e9fb5
|