@useorgx/wizard 0.1.51 → 0.1.55

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/cli.js CHANGED
@@ -1,27 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // _sentry-injection-stub
4
- !(function() {
5
- try {
6
- var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
7
- e.SENTRY_RELEASE = { id: "@useorgx/wizard@0.1.51" };
8
- } catch (e2) {
9
- }
10
- })();
11
-
12
- // sentry-debug-id-stub:_sentry-debug-id-injection-stub?sentry-module-id=50d660b4-210d-47c3-aad7-7a156a2728dc
13
- !(function() {
14
- try {
15
- var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
16
- var n = new e.Error().stack;
17
- n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "3d12c6ba-ce58-4cb0-8416-25155e8d07f5", e._sentryDebugIdIdentifier = "sentry-dbid-3d12c6ba-ce58-4cb0-8416-25155e8d07f5");
18
- } catch (e2) {
19
- }
20
- })();
21
-
22
3
  // src/cli.ts
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]="707a7fe5-404e-5aec-9c75-30f0f5d859d9")}catch(e){}}();
23
6
  import * as clack from "@clack/prompts";
24
- import { spawnSync as spawnSync3 } from "child_process";
7
+ import { spawnSync as spawnSync5 } from "child_process";
25
8
  import { readFileSync as readFileSync8 } from "fs";
26
9
  import { hostname } from "os";
27
10
  import { resolve as resolve3 } from "path";
@@ -99,6 +82,7 @@ var CLAUDE_DIR = join(HOME, ".claude");
99
82
  var CURSOR_DIR = join(HOME, ".cursor");
100
83
  var CODEX_DIR = join(HOME, ".codex");
101
84
  var OPENCLAW_DIR = join(HOME, ".openclaw");
85
+ var DEEPSEEK_HARNESS_DIR = process.env.DSH_HOME?.trim() || join(HOME, ".dsh");
102
86
  var AGENTS_DIR = join(HOME, ".agents");
103
87
  var CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, "projects");
104
88
  var CODEX_SESSIONS_DIR = join(CODEX_DIR, "sessions");
@@ -142,6 +126,15 @@ var CLAUDE_INSTALL_PATHS = uniquePaths([CLAUDE_DIR]);
142
126
  var CURSOR_INSTALL_PATHS = uniquePaths([CURSOR_DIR]);
143
127
  var CODEX_INSTALL_PATHS = uniquePaths([CODEX_DIR]);
144
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
+ ]);
145
138
  var VSCODE_MCP_PATHS = uniquePaths([
146
139
  join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
147
140
  join(XDG_CONFIG_HOME, "Code", "User", "mcp.json"),
@@ -1115,6 +1108,34 @@ async function exchangeCodeForTokens(options) {
1115
1108
  ...typeof data.scope === "string" ? { scope: data.scope } : {}
1116
1109
  };
1117
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
+ }
1118
1139
  async function startPkceLogin(options = {}) {
1119
1140
  const port = options.preferredPort ?? ORGX_WIZARD_OAUTH_PREFERRED_PORT;
1120
1141
  const scope = options.scope ?? ORGX_WIZARD_OAUTH_SCOPE;
@@ -1169,6 +1190,7 @@ var SURFACE_NAMES = [
1169
1190
  "claude",
1170
1191
  "cursor",
1171
1192
  "codex",
1193
+ "deepseek",
1172
1194
  "openclaw",
1173
1195
  "vscode",
1174
1196
  "windsurf",
@@ -1179,6 +1201,7 @@ var AUTOMATED_SURFACE_NAMES = [
1179
1201
  "claude",
1180
1202
  "cursor",
1181
1203
  "codex",
1204
+ "deepseek",
1182
1205
  "openclaw",
1183
1206
  "vscode",
1184
1207
  "windsurf",
@@ -2142,16 +2165,13 @@ async function checkWorkspaceConnectivity(options = {}) {
2142
2165
  import { spawn } from "child_process";
2143
2166
  import {
2144
2167
  existsSync as existsSync4,
2145
- mkdirSync as mkdirSync2,
2146
- mkdtempSync,
2147
- readFileSync as readFileSync2,
2148
- readdirSync as readdirSync2,
2149
- rmSync,
2150
- statSync as statSync2,
2151
- writeFileSync as writeFileSync2
2168
+ mkdirSync as mkdirSync3,
2169
+ mkdtempSync as mkdtempSync2,
2170
+ rmSync as rmSync2,
2171
+ writeFileSync as writeFileSync3
2152
2172
  } from "fs";
2153
2173
  import { tmpdir } from "os";
2154
- import { dirname as dirname3, join as join3, relative } from "path";
2174
+ import { dirname as dirname4, join as join4 } from "path";
2155
2175
 
2156
2176
  // src/surfaces/mcp-config.ts
2157
2177
  import * as TOML from "@iarna/toml";
@@ -2498,6 +2518,10 @@ var SURFACE_LOCATORS = {
2498
2518
  configPaths: CODEX_CONFIG_PATHS,
2499
2519
  installPaths: CODEX_INSTALL_PATHS
2500
2520
  },
2521
+ deepseek: {
2522
+ configPaths: [DEEPSEEK_HARNESS_PROFILE_PATH],
2523
+ installPaths: DEEPSEEK_HARNESS_INSTALL_PATHS
2524
+ },
2501
2525
  openclaw: {
2502
2526
  configPaths: OPENCLAW_CONFIG_PATHS,
2503
2527
  installPaths: OPENCLAW_INSTALL_PATHS
@@ -2561,10 +2585,359 @@ function detectSurface(name, exists = existsSync2) {
2561
2585
  return detection;
2562
2586
  }
2563
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
+
2564
2937
  // src/lib/skills.ts
2565
2938
  import { createHash as createHash2 } from "crypto";
2566
- import { existsSync as existsSync3, readdirSync } from "fs";
2567
- import { basename, join as join2 } from "path";
2939
+ import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
2940
+ import { basename, join as join3 } from "path";
2568
2941
  var DEFAULT_ORGX_SKILL_PACKS = [
2569
2942
  "morning-briefing",
2570
2943
  "initiative-kickoff",
@@ -2662,7 +3035,7 @@ function defaultExtensionTitle(skillId, scope) {
2662
3035
  return `${prefix} ${skillId} behavior`;
2663
3036
  }
2664
3037
  function extensionFilePath(skillId, scope, extensionsDir = ORGX_SKILL_EXTENSIONS_DIR) {
2665
- return join2(extensionsDir, `${scope}.${skillId}.md`);
3038
+ return join3(extensionsDir, `${scope}.${skillId}.md`);
2666
3039
  }
2667
3040
  function extensionTemplate(input) {
2668
3041
  const body = input.content?.trim() ? input.content.trim() : [
@@ -2746,8 +3119,8 @@ function listSkillExtensions(options = {}) {
2746
3119
  if (!existsSync3(extensionsDir)) {
2747
3120
  return [];
2748
3121
  }
2749
- return readdirSync(extensionsDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => {
2750
- const path = join2(extensionsDir, entry.name);
3122
+ return readdirSync2(extensionsDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => {
3123
+ const path = join3(extensionsDir, entry.name);
2751
3124
  const content = readTextIfExists(path);
2752
3125
  return content === null ? null : parseSkillExtension(path, content);
2753
3126
  }).filter((entry) => Boolean(entry)).sort((left, right) => left.id.localeCompare(right.id));
@@ -3019,7 +3392,7 @@ async function installSkillPack(skillName, claudeSkillsDir, fetchImpl, ref, trac
3019
3392
  const content = relativePath === "SKILL.md" ? composeSkillContent(skillName, coreContent, tracking.extensions) : coreContent;
3020
3393
  writes.push(
3021
3394
  writeManagedFile(
3022
- join2(claudeSkillsDir, skillName, relativePath),
3395
+ join3(claudeSkillsDir, skillName, relativePath),
3023
3396
  content,
3024
3397
  `${skillName}/${relativePath}`,
3025
3398
  file.sourceUrl,
@@ -3158,8 +3531,6 @@ function getSkillStatus(options = {}) {
3158
3531
  var DEFAULT_ORGX_PLUGIN_TARGETS = ["cursor", "claude", "codex", "openclaw"];
3159
3532
  var ORGX_PLUGIN_GITHUB_OWNER = "useorgx";
3160
3533
  var ORGX_PLUGIN_GITHUB_REF = "main";
3161
- var ORGX_CLAUDE_PLUGIN_NAME = "orgx-claude-code-plugin";
3162
- var ORGX_CLAUDE_MARKETPLACE_NAME = "orgx-local";
3163
3534
  var ORGX_CODEX_PLUGIN_NAME = "orgx-codex-plugin";
3164
3535
  var ORGX_CURSOR_PLUGIN_NAME = "cursor-plugin";
3165
3536
  var ORGX_OPENCLAW_PLUGIN_ID = "orgx";
@@ -3167,16 +3538,14 @@ var ORGX_OPENCLAW_PLUGIN_PACKAGE_NAME = "@useorgx/openclaw-plugin";
3167
3538
  var CLAUDE_PLUGIN_SYNC_SPEC = {
3168
3539
  owner: ORGX_PLUGIN_GITHUB_OWNER,
3169
3540
  repo: ORGX_CLAUDE_PLUGIN_NAME,
3170
- ref: ORGX_PLUGIN_GITHUB_REF,
3541
+ ref: ORGX_CLAUDE_PLUGIN_REF,
3171
3542
  include: [
3172
3543
  { localPath: ".claude-plugin", remotePath: ".claude-plugin" },
3173
- { localPath: "agents", remotePath: "agents" },
3544
+ { localPath: ".mcp.json", remotePath: ".mcp.json" },
3174
3545
  { localPath: "commands", remotePath: "commands" },
3175
- { localPath: "hooks", remotePath: "hooks" },
3176
- { localPath: "lib", remotePath: "lib" },
3177
- { localPath: "scripts", remotePath: "scripts" },
3178
3546
  { localPath: "skills", remotePath: "skills" }
3179
- ]
3547
+ ],
3548
+ validate: validateClaudePluginBundle
3180
3549
  };
3181
3550
  var CODEX_PLUGIN_SYNC_SPEC = {
3182
3551
  owner: ORGX_PLUGIN_GITHUB_OWNER,
@@ -3299,7 +3668,7 @@ async function listRemoteRepoFiles(spec, path, localPath, fetchImpl) {
3299
3668
  ...await listRemoteRepoFiles(
3300
3669
  spec,
3301
3670
  entry.path,
3302
- join3(localPath, entry.name),
3671
+ join4(localPath, entry.name),
3303
3672
  fetchImpl
3304
3673
  )
3305
3674
  );
@@ -3309,7 +3678,7 @@ async function listRemoteRepoFiles(spec, path, localPath, fetchImpl) {
3309
3678
  throw new Error(`GitHub did not provide a download URL for '${entry.path}'.`);
3310
3679
  }
3311
3680
  files.push({
3312
- localPath: join3(localPath, entry.name),
3681
+ localPath: join4(localPath, entry.name),
3313
3682
  path: entry.path,
3314
3683
  sourceUrl: entry.download_url
3315
3684
  });
@@ -3345,88 +3714,25 @@ async function fetchRemoteBytes(sourceUrl, fetchImpl) {
3345
3714
  }
3346
3715
  return Buffer.from(await response.arrayBuffer());
3347
3716
  }
3348
- function readBytesIfExists(path) {
3349
- if (!existsSync4(path)) return null;
3350
- try {
3351
- if (!statSync2(path).isFile()) {
3352
- return null;
3353
- }
3354
- return readFileSync2(path);
3355
- } catch (error) {
3356
- const code = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
3357
- if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR") {
3358
- return null;
3359
- }
3360
- throw error;
3361
- }
3362
- }
3363
- function writeBytesIfChanged(path, bytes) {
3364
- const existing = readBytesIfExists(path);
3365
- if (existing && Buffer.compare(existing, bytes) === 0) {
3366
- return false;
3367
- }
3368
- mkdirSync2(dirname3(path), { recursive: true });
3369
- writeFileSync2(path, bytes);
3370
- return true;
3371
- }
3372
3717
  function removePathIfExists(path) {
3373
3718
  if (!existsSync4(path)) return false;
3374
- rmSync(path, { force: true, recursive: true });
3719
+ rmSync2(path, { force: true, recursive: true });
3375
3720
  return true;
3376
3721
  }
3377
- function listRelativeFiles(root, base = root) {
3378
- if (!existsSync4(root)) return [];
3379
- if (!statSync2(root).isDirectory()) {
3380
- return [];
3381
- }
3382
- const files = [];
3383
- for (const entry of readdirSync2(root, { withFileTypes: true })) {
3384
- const nextPath = join3(root, entry.name);
3385
- if (entry.isDirectory()) {
3386
- files.push(...listRelativeFiles(nextPath, base));
3387
- continue;
3388
- }
3389
- if (entry.isFile()) {
3390
- files.push(relative(base, nextPath));
3391
- }
3392
- }
3393
- return files.sort();
3394
- }
3395
- function pruneEmptyDirectories(root, current = root) {
3396
- if (!existsSync4(current) || !statSync2(current).isDirectory()) {
3397
- return false;
3398
- }
3399
- let changed = false;
3400
- for (const entry of readdirSync2(current, { withFileTypes: true })) {
3401
- if (!entry.isDirectory()) continue;
3402
- changed = pruneEmptyDirectories(root, join3(current, entry.name)) || changed;
3403
- }
3404
- if (current !== root && readdirSync2(current).length === 0) {
3405
- rmSync(current, { force: true, recursive: true });
3406
- return true;
3407
- }
3408
- return changed;
3409
- }
3410
3722
  async function syncManagedRepoTree(spec, destinationRoot, fetchImpl) {
3411
3723
  const remoteFiles = await collectRemoteRepoFiles(spec, fetchImpl);
3412
- let changed = false;
3413
- const expected = new Set(remoteFiles.map((file) => file.localPath));
3414
- if (existsSync4(destinationRoot) && !statSync2(destinationRoot).isDirectory()) {
3415
- rmSync(destinationRoot, { force: true, recursive: true });
3416
- changed = true;
3417
- }
3418
- for (const file of listRelativeFiles(destinationRoot)) {
3419
- if (expected.has(file)) continue;
3420
- rmSync(join3(destinationRoot, file), { force: true });
3421
- changed = true;
3422
- }
3423
- changed = pruneEmptyDirectories(destinationRoot) || changed;
3724
+ const fetchedFiles = [];
3424
3725
  for (const file of remoteFiles) {
3425
- const bytes = await fetchRemoteBytes(file.sourceUrl, fetchImpl);
3426
- if (writeBytesIfChanged(join3(destinationRoot, file.localPath), bytes)) {
3427
- changed = true;
3428
- }
3726
+ fetchedFiles.push({
3727
+ ...file,
3728
+ bytes: await fetchRemoteBytes(file.sourceUrl, fetchImpl)
3729
+ });
3429
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
+ );
3430
3736
  return { changed, fileCount: remoteFiles.length };
3431
3737
  }
3432
3738
  function serializeJson(value) {
@@ -3439,8 +3745,8 @@ function writeJsonIfChanged(path, value) {
3439
3745
  if (existing === next) {
3440
3746
  return false;
3441
3747
  }
3442
- mkdirSync2(dirname3(path), { recursive: true });
3443
- writeFileSync2(path, next, "utf8");
3748
+ mkdirSync3(dirname4(path), { recursive: true });
3749
+ writeFileSync3(path, next, "utf8");
3444
3750
  return true;
3445
3751
  }
3446
3752
  function buildClaudeMarketplaceManifest() {
@@ -3454,7 +3760,7 @@ function buildClaudeMarketplaceManifest() {
3454
3760
  plugins: [
3455
3761
  {
3456
3762
  name: ORGX_CLAUDE_PLUGIN_NAME,
3457
- description: "OrgX MCP tools and runtime telemetry hooks for Claude Code.",
3763
+ description: "Connect Claude Code to a focused, non-destructive, closed-world OrgX status profile through native OAuth.",
3458
3764
  source: `./plugins/${ORGX_CLAUDE_PLUGIN_NAME}`
3459
3765
  }
3460
3766
  ]
@@ -3511,7 +3817,7 @@ function removeCodexMarketplaceEntry(path) {
3511
3817
  return false;
3512
3818
  }
3513
3819
  if (nextPlugins.length === 0) {
3514
- rmSync(path, { force: true });
3820
+ rmSync2(path, { force: true });
3515
3821
  return true;
3516
3822
  }
3517
3823
  return writeJsonIfChanged(path, {
@@ -3523,16 +3829,21 @@ function codexMarketplaceHasOrgxEntry(path) {
3523
3829
  const { plugins } = readMarketplacePlugins(path);
3524
3830
  return plugins.some((plugin) => plugin.name === ORGX_CODEX_PLUGIN_NAME);
3525
3831
  }
3526
- function extractClaudePluginNames(payload) {
3832
+ function extractClaudePluginInstallations(payload) {
3527
3833
  try {
3528
3834
  const parsed = JSON.parse(payload);
3529
3835
  if (!Array.isArray(parsed)) return [];
3530
3836
  return parsed.flatMap((entry) => {
3531
- if (typeof entry === "string") return [entry];
3837
+ if (typeof entry === "string") return [{ id: entry }];
3532
3838
  if (!entry || typeof entry !== "object") return [];
3533
- if (typeof entry.name === "string") return [entry.name];
3534
- if (typeof entry.id === "string") return [entry.id];
3535
- 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
+ }];
3536
3847
  });
3537
3848
  } catch {
3538
3849
  return [];
@@ -3617,11 +3928,30 @@ async function getClaudeInstallState(runner) {
3617
3928
  if (result.exitCode !== 0) {
3618
3929
  return { available: true, installed: false };
3619
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
+ );
3620
3935
  return {
3621
3936
  available: true,
3622
- installed: extractClaudePluginNames(result.stdout).includes(ORGX_CLAUDE_PLUGIN_NAME)
3937
+ installed: Boolean(installation),
3938
+ ...installation?.version ? { version: installation.version } : {}
3623
3939
  };
3624
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
+ }
3625
3955
  async function getOpenclawInstallState(runner) {
3626
3956
  const available = detectSurface("openclaw").detected || await commandExists("openclaw", runner);
3627
3957
  if (!available) {
@@ -3637,17 +3967,17 @@ async function getOpenclawInstallState(runner) {
3637
3967
  };
3638
3968
  }
3639
3969
  function cursorPluginManifestPath(paths) {
3640
- return join3(paths.cursorPluginDir, ".cursor-plugin", "plugin.json");
3970
+ return join4(paths.cursorPluginDir, ".cursor-plugin", "plugin.json");
3641
3971
  }
3642
3972
  function cursorPluginMcpPath(paths) {
3643
- return join3(paths.cursorPluginDir, ".mcp.json");
3973
+ return join4(paths.cursorPluginDir, ".mcp.json");
3644
3974
  }
3645
3975
  function isCursorPluginInstalled(paths) {
3646
3976
  return existsSync4(cursorPluginManifestPath(paths)) && existsSync4(cursorPluginMcpPath(paths));
3647
3977
  }
3648
3978
  function getCursorToolingState(options = {}) {
3649
3979
  const paths = resolvePluginPaths(options.paths);
3650
- const mcpFile = options.mcpPath ?? CURSOR_MCP_PATH ?? join3(CURSOR_DIR, "mcp.json");
3980
+ const mcpFile = options.mcpPath ?? CURSOR_MCP_PATH ?? join4(CURSOR_DIR, "mcp.json");
3651
3981
  const mcpText = readTextIfExists(mcpFile);
3652
3982
  const inspection = inspectCursorMcpConfig(mcpText);
3653
3983
  return {
@@ -3657,7 +3987,7 @@ function getCursorToolingState(options = {}) {
3657
3987
  };
3658
3988
  }
3659
3989
  function isCursorPluginAvailable(paths) {
3660
- return detectSurface("cursor").detected || existsSync4(paths.cursorPluginDir) || existsSync4(dirname3(paths.cursorPluginDir)) || readTextIfExists(paths.cursorRulePath) !== null;
3990
+ return detectSurface("cursor").detected || existsSync4(paths.cursorPluginDir) || existsSync4(dirname4(paths.cursorPluginDir)) || readTextIfExists(paths.cursorRulePath) !== null;
3661
3991
  }
3662
3992
  function buildCursorStatus(paths) {
3663
3993
  const existingRules = readTextIfExists(paths.cursorRulePath);
@@ -3843,36 +4173,44 @@ async function installClaudePlugin(paths, fetchImpl, runner) {
3843
4173
  throw new Error(formatCommandFailure("claude", ["plugin", "marketplace", "add", paths.claudeMarketplaceDir], marketplaceAdd));
3844
4174
  }
3845
4175
  let installedChanged = false;
4176
+ let updatedChanged = false;
3846
4177
  if (!state.installed) {
3847
- const install = await runner("claude", [
4178
+ const installArgs = [
3848
4179
  "plugin",
3849
4180
  "install",
3850
4181
  `${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`,
3851
4182
  "--scope",
3852
4183
  "user"
3853
- ]);
4184
+ ];
4185
+ const install = await runner("claude", installArgs);
3854
4186
  if (install.exitCode !== 0) {
3855
4187
  throw new Error(
3856
- formatCommandFailure(
3857
- "claude",
3858
- [
3859
- "plugin",
3860
- "install",
3861
- `${ORGX_CLAUDE_PLUGIN_NAME}@${ORGX_CLAUDE_MARKETPLACE_NAME}`,
3862
- "--scope",
3863
- "user"
3864
- ],
3865
- install
3866
- )
4188
+ formatCommandFailure("claude", installArgs, install)
3867
4189
  );
3868
4190
  }
4191
+ await requireManagedClaudePluginVersion(runner, "install");
3869
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;
3870
4207
  }
3871
- 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";
3872
4210
  return {
3873
4211
  target: "claude",
3874
4212
  changed,
3875
- message: changed ? `Synced ${syncResult.fileCount} Claude plugin files and ensured the plugin is installed.` : "Claude Code plugin is already installed and up to date."
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.`
3876
4214
  };
3877
4215
  }
3878
4216
  async function installCodexPlugin(paths, fetchImpl, runner) {
@@ -3911,10 +4249,10 @@ async function installOpenclawPlugin(fetchImpl, runner) {
3911
4249
  }
3912
4250
  const { tarballUrl, version } = await resolveOpenclawTarball(fetchImpl);
3913
4251
  const tarballBytes = await fetchRemoteBytes(tarballUrl, fetchImpl);
3914
- const tempRoot = mkdtempSync(join3(tmpdir(), "orgx-wizard-openclaw-"));
3915
- const archivePath = join3(tempRoot, `orgx-openclaw-plugin-${version}.tgz`);
4252
+ const tempRoot = mkdtempSync2(join4(tmpdir(), "orgx-wizard-openclaw-"));
4253
+ const archivePath = join4(tempRoot, `orgx-openclaw-plugin-${version}.tgz`);
3916
4254
  try {
3917
- writeFileSync2(archivePath, tarballBytes);
4255
+ writeFileSync3(archivePath, tarballBytes);
3918
4256
  const install = await runner("openclaw", ["plugins", "install", archivePath]);
3919
4257
  if (install.exitCode !== 0) {
3920
4258
  throw new Error(
@@ -3922,7 +4260,7 @@ async function installOpenclawPlugin(fetchImpl, runner) {
3922
4260
  );
3923
4261
  }
3924
4262
  } finally {
3925
- rmSync(tempRoot, { force: true, recursive: true });
4263
+ rmSync2(tempRoot, { force: true, recursive: true });
3926
4264
  }
3927
4265
  return {
3928
4266
  target: "openclaw",
@@ -4096,6 +4434,134 @@ function countPluginReportChanges(report) {
4096
4434
  return report.results.filter((result) => result.changed).length;
4097
4435
  }
4098
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
+
4099
4565
  // src/surfaces/registry.ts
4100
4566
  var AUTH_SETUP_HINT = "orgx-wizard auth login";
4101
4567
  var AUTH_SET_KEY_HINT = "orgx-wizard auth set-key";
@@ -4130,6 +4596,19 @@ function automatedSurfaceStatus(name) {
4130
4596
  const detection = detectSurface(name);
4131
4597
  const path = detection.existingPath ?? detection.preferredPath;
4132
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
+ }
4133
4612
  if (name === "claude") {
4134
4613
  const inspection2 = inspectClaudeMcpConfig(path ? readTextIfExists(path) : null);
4135
4614
  const configured = inspection2.hostedConfigured === true && (openclaw.detected ? inspection2.localConfigured === true : true);
@@ -4417,6 +4896,15 @@ async function addAutomatedSurface(name) {
4417
4896
  message: openclaw.detected ? "OrgX is connected in Codex with the local OpenClaw bridge." : "OrgX cloud MCP is connected in Codex."
4418
4897
  };
4419
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
+ }
4420
4908
  case "openclaw": {
4421
4909
  const previous = readTextIfExists(path);
4422
4910
  const auth = await resolveOrgxAuth();
@@ -4514,6 +5002,15 @@ function removeAutomatedSurface(name) {
4514
5002
  message: "OrgX connection was removed from Codex."
4515
5003
  };
4516
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
+ }
4517
5014
  case "openclaw": {
4518
5015
  const previous = readTextIfExists(path);
4519
5016
  const next = removeOpenClawConfig(previous);
@@ -5247,8 +5744,8 @@ async function ensureOnboardingTask(workspace, options = {}) {
5247
5744
 
5248
5745
  // src/lib/local-skill-discovery.ts
5249
5746
  import { createHash as createHash3 } from "crypto";
5250
- import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
5251
- import { basename as basename2, join as join4, relative as relative2 } from "path";
5747
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
5748
+ import { basename as basename2, join as join5, relative } from "path";
5252
5749
  var DEFAULT_MAX_BYTES = 48e3;
5253
5750
  var DEFAULT_LIMIT = 12;
5254
5751
  var IGNORED_DIRS = /* @__PURE__ */ new Set([".git", ".next", ".turbo", "build", "dist", "node_modules"]);
@@ -5266,26 +5763,26 @@ function hash(value, length = 10) {
5266
5763
  }
5267
5764
  function safeStat(path) {
5268
5765
  try {
5269
- return statSync3(path);
5766
+ return statSync2(path);
5270
5767
  } catch {
5271
5768
  return null;
5272
5769
  }
5273
5770
  }
5274
5771
  function defaultRoots(input) {
5275
5772
  return {
5276
- agents: [join4(input.home, ".agents", "skills")],
5277
- claude: [join4(input.home, ".claude", "skills"), join4(input.cwd, ".claude", "skills")],
5278
- codex: [join4(input.home, ".codex", "skills"), join4(input.cwd, ".codex", "skills")],
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")],
5279
5776
  opencode: [
5280
- join4(input.home, ".opencode", "skills"),
5281
- join4(input.home, ".config", "opencode", "skills"),
5282
- join4(input.home, "Library", "Application Support", "opencode", "skills"),
5283
- join4(input.cwd, ".opencode", "skills")
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")
5284
5781
  ],
5285
5782
  workspace: [
5286
- join4(input.cwd, "skills"),
5287
- join4(input.cwd, ".agents", "skills"),
5288
- join4(input.cwd, ".orgx", "skills")
5783
+ join5(input.cwd, "skills"),
5784
+ join5(input.cwd, ".agents", "skills"),
5785
+ join5(input.cwd, ".orgx", "skills")
5289
5786
  ]
5290
5787
  };
5291
5788
  }
@@ -5307,7 +5804,7 @@ function walkSkillFiles(root, maxFiles = 200) {
5307
5804
  }
5308
5805
  for (const entry of entries) {
5309
5806
  if (IGNORED_DIRS.has(entry.name)) continue;
5310
- const path = join4(current, entry.name);
5807
+ const path = join5(current, entry.name);
5311
5808
  if (entry.isDirectory()) {
5312
5809
  stack.push(path);
5313
5810
  } else if (entry.isFile() && /\.(md|mdc|txt)$/i.test(entry.name)) {
@@ -5438,7 +5935,7 @@ function buildLocalSkillExtensionContent(candidates, context) {
5438
5935
  "",
5439
5936
  `## ${candidate.title}`,
5440
5937
  "",
5441
- `- Source: ${candidate.source} (${relative2(process.cwd(), candidate.path)})`,
5938
+ `- Source: ${candidate.source} (${relative(process.cwd(), candidate.path)})`,
5442
5939
  `- Suggested agents: ${candidate.agentDomains.join(", ")}`,
5443
5940
  `- Preserve: ${candidate.snippet || "local workflow preference from this skill file."}`
5444
5941
  );
@@ -5714,7 +6211,7 @@ function initializeWizardSentry() {
5714
6211
  Sentry.init({
5715
6212
  dsn,
5716
6213
  environment: process.env.ORGX_SENTRY_ENVIRONMENT || "production",
5717
- release: `@useorgx/wizard@${"0.1.51"}`,
6214
+ release: "useorgx-wizard@0.1.55",
5718
6215
  tracesSampleRate: sampleRate(process.env.ORGX_SENTRY_TRACES_SAMPLE_RATE),
5719
6216
  enableLogs: true,
5720
6217
  sendDefaultPii: false,
@@ -6432,8 +6929,8 @@ async function fetchOnboardingState(auth) {
6432
6929
  }
6433
6930
 
6434
6931
  // src/lib/ai-session-import.ts
6435
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
6436
- import { basename as basename3, join as join5, relative as relative3 } from "path";
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";
6437
6934
  var AI_SESSION_SOURCES = ["codex", "claude"];
6438
6935
  var DEFAULT_LIMIT_PER_SOURCE = 3;
6439
6936
  var DEFAULT_SINCE_DAYS = 30;
@@ -6599,10 +7096,10 @@ function collectJsonlFiles(root, source) {
6599
7096
  continue;
6600
7097
  }
6601
7098
  for (const entry of entries) {
6602
- const path = join5(current, entry);
7099
+ const path = join6(current, entry);
6603
7100
  let stats;
6604
7101
  try {
6605
- stats = statSync4(path);
7102
+ stats = statSync3(path);
6606
7103
  } catch {
6607
7104
  continue;
6608
7105
  }
@@ -6620,7 +7117,7 @@ function collectJsonlFiles(root, source) {
6620
7117
  function readSessionImport(candidate, root, options) {
6621
7118
  let stats;
6622
7119
  try {
6623
- stats = statSync4(candidate.path);
7120
+ stats = statSync3(candidate.path);
6624
7121
  } catch {
6625
7122
  return null;
6626
7123
  }
@@ -6638,7 +7135,7 @@ function readSessionImport(candidate, root, options) {
6638
7135
  }
6639
7136
  const deduped = [...new Set(relevantLines)].slice(0, 80);
6640
7137
  if (deduped.length === 0) return null;
6641
- const relativePath = relative3(root, candidate.path);
7138
+ const relativePath = relative2(root, candidate.path);
6642
7139
  return {
6643
7140
  import: {
6644
7141
  sourceId: `${candidate.source}:${basename3(candidate.path, ".jsonl")}`,
@@ -6713,9 +7210,9 @@ function loadAiSessionImports(options) {
6713
7210
  // src/lib/work-graph-source-adapters.ts
6714
7211
  import { createHash as createHash4 } from "crypto";
6715
7212
  import { execFileSync } from "child_process";
6716
- import { closeSync, existsSync as existsSync7, openSync, readFileSync as readFileSync5, readdirSync as readdirSync5, readSync, statSync as statSync5 } from "fs";
7213
+ import { closeSync, existsSync as existsSync7, openSync, readFileSync as readFileSync5, readdirSync as readdirSync5, readSync, statSync as statSync4 } from "fs";
6717
7214
  import { homedir as homedir2 } from "os";
6718
- import { basename as basename4, join as join6, resolve } from "path";
7215
+ import { basename as basename4, join as join7, resolve } from "path";
6719
7216
  var CLIENT_SOURCES = ["claude_code", "codex", "opencode", "goose", "cursor", "github", "slack"];
6720
7217
  var DEFAULT_LIMIT_PER_SOURCE2 = 8;
6721
7218
  var DEFAULT_SINCE_DAYS2 = 45;
@@ -6742,7 +7239,7 @@ function expandPath(path, env) {
6742
7239
  }
6743
7240
  function safeStat2(path) {
6744
7241
  try {
6745
- return statSync5(path);
7242
+ return statSync4(path);
6746
7243
  } catch {
6747
7244
  return null;
6748
7245
  }
@@ -6763,7 +7260,7 @@ function walkFiles(root, predicate, maxFiles = 500) {
6763
7260
  }
6764
7261
  for (const entry of entries) {
6765
7262
  if (ignored.has(entry)) continue;
6766
- const path = join6(current, entry);
7263
+ const path = join7(current, entry);
6767
7264
  const stats = safeStat2(path);
6768
7265
  if (!stats) continue;
6769
7266
  if (stats.isDirectory()) {
@@ -7017,8 +7514,8 @@ function readJsonlCandidate(candidate, options) {
7017
7514
  searchedSessions: 0
7018
7515
  };
7019
7516
  }
7020
- const window2 = readTextWindow(candidate.path, stats, options.maxBytesPerFile);
7021
- const lines = window2.text.split(/\r?\n/);
7517
+ const window = readTextWindow(candidate.path, stats, options.maxBytesPerFile);
7518
+ const lines = window.text.split(/\r?\n/);
7022
7519
  const fallbackTimestamp = new Date(stats.mtimeMs).toISOString();
7023
7520
  const sessionId = basename4(candidate.path).replace(/\.[^.]+$/, "");
7024
7521
  const events = [];
@@ -7054,7 +7551,7 @@ function readJsonlCandidate(candidate, options) {
7054
7551
  events,
7055
7552
  filesRead: 1,
7056
7553
  filesSkipped: [],
7057
- notes: window2.truncated ? [`Read the latest ${options.maxBytesPerFile} bytes from oversized JSONL source instead of skipping it.`] : [],
7554
+ notes: window.truncated ? [`Read the latest ${options.maxBytesPerFile} bytes from oversized JSONL source instead of skipping it.`] : [],
7058
7555
  searchedSessions: 1
7059
7556
  };
7060
7557
  }
@@ -12999,22 +13496,22 @@ function buildWorkGraphHookReplayPatch(readResult) {
12999
13496
  }
13000
13497
 
13001
13498
  // src/lib/runtime-hooks.ts
13002
- import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "fs";
13499
+ import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
13003
13500
  import { homedir as homedir3 } from "os";
13004
- import { dirname as dirname4, join as join7 } from "path";
13501
+ import { dirname as dirname5, join as join8 } from "path";
13005
13502
  var HOOK_MARKER = "orgx-session-hook.mjs";
13006
13503
  var EMIT_HOOK_MARKER = "orgx-emit-execution-graph.mjs";
13007
13504
  var HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PermissionRequest", "Stop"];
13008
13505
  var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "SubagentStop", "Stop", "SessionEnd"];
13009
13506
  function defaultPaths(options = {}) {
13010
- const hookDir = join7(ORGX_WIZARD_CONFIG_HOME, "hooks");
13507
+ const hookDir = join8(ORGX_WIZARD_CONFIG_HOME, "hooks");
13011
13508
  return {
13012
- claudeSettingsPath: options.claudeSettingsPath ?? join7(CLAUDE_DIR, "settings.json"),
13013
- codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join7(CODEX_DIR, "config.toml"),
13014
- codexHooksPath: options.codexHooksPath ?? join7(CODEX_DIR, "hooks.json"),
13015
- hookScriptPath: options.hookScriptPath ?? join7(hookDir, HOOK_MARKER),
13016
- emitHookScriptPath: options.emitHookScriptPath ?? join7(hookDir, EMIT_HOOK_MARKER),
13017
- outboxPath: options.outboxPath ?? join7(hookDir, "events.jsonl")
13509
+ claudeSettingsPath: options.claudeSettingsPath ?? join8(CLAUDE_DIR, "settings.json"),
13510
+ codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join8(CODEX_DIR, "config.toml"),
13511
+ codexHooksPath: options.codexHooksPath ?? join8(CODEX_DIR, "hooks.json"),
13512
+ hookScriptPath: options.hookScriptPath ?? join8(hookDir, HOOK_MARKER),
13513
+ emitHookScriptPath: options.emitHookScriptPath ?? join8(hookDir, EMIT_HOOK_MARKER),
13514
+ outboxPath: options.outboxPath ?? join8(hookDir, "events.jsonl")
13018
13515
  };
13019
13516
  }
13020
13517
  function countJsonlLines(path) {
@@ -13396,7 +13893,7 @@ function installRuntimeHooks(targets, options = {}) {
13396
13893
  hookScript: false,
13397
13894
  emitHookScript: false
13398
13895
  };
13399
- mkdirSync3(dirname4(paths.hookScriptPath), { recursive: true, mode: 448 });
13896
+ mkdirSync4(dirname5(paths.hookScriptPath), { recursive: true, mode: 448 });
13400
13897
  const scriptContent = buildRuntimeHookScriptContent();
13401
13898
  if (readTextIfExists(paths.hookScriptPath) !== scriptContent) {
13402
13899
  const backup = backupExisting(paths.hookScriptPath, now);
@@ -13404,7 +13901,7 @@ function installRuntimeHooks(targets, options = {}) {
13404
13901
  writeTextFile(paths.hookScriptPath, scriptContent, { mode: 448 });
13405
13902
  changed.hookScript = true;
13406
13903
  }
13407
- mkdirSync3(dirname4(paths.emitHookScriptPath), { recursive: true, mode: 448 });
13904
+ mkdirSync4(dirname5(paths.emitHookScriptPath), { recursive: true, mode: 448 });
13408
13905
  const emitScriptContent = buildExecutionGraphEmitScriptContent();
13409
13906
  if (readTextIfExists(paths.emitHookScriptPath) !== emitScriptContent) {
13410
13907
  const backup = backupExisting(paths.emitHookScriptPath, now);
@@ -14030,6 +14527,73 @@ async function requestWorkloadDiagnosis(input, options = {}) {
14030
14527
  return parsed.data;
14031
14528
  }
14032
14529
 
14530
+ // src/lib/deepseek-launcher.ts
14531
+ import { spawnSync as spawnSync4 } from "child_process";
14532
+ async function resolveFreshMcpAuth(deps) {
14533
+ const authPath = deps.authPath ?? ORGX_WIZARD_AUTH_PATH;
14534
+ const readAuth = deps.readAuth ?? readWizardAuth;
14535
+ const stored = await readAuth(authPath);
14536
+ if (!stored) {
14537
+ throw new Error("OrgX is not paired. Run orgx-wizard auth login first.");
14538
+ }
14539
+ if (stored.source !== "pkce") return stored;
14540
+ if (!stored.refreshToken || !stored.oauthClientId) {
14541
+ throw new Error("OrgX browser authorization cannot be refreshed. Run orgx-wizard auth login again.");
14542
+ }
14543
+ const refresh = deps.refreshToken ?? refreshAccessToken;
14544
+ let refreshed;
14545
+ try {
14546
+ refreshed = await refresh({
14547
+ refreshToken: stored.refreshToken,
14548
+ clientId: stored.oauthClientId
14549
+ });
14550
+ } catch (error) {
14551
+ const detail = error instanceof Error ? error.message : String(error);
14552
+ throw new Error(`OrgX authorization refresh failed. Run orgx-wizard auth login again. ${detail}`);
14553
+ }
14554
+ const writeAuth = deps.writeAuth ?? writeWizardAuth;
14555
+ return writeAuth(
14556
+ {
14557
+ apiKey: refreshed.access_token,
14558
+ baseUrl: stored.baseUrl,
14559
+ verifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
14560
+ source: "pkce",
14561
+ refreshToken: refreshed.refresh_token ?? stored.refreshToken,
14562
+ oauthClientId: stored.oauthClientId
14563
+ },
14564
+ authPath
14565
+ );
14566
+ }
14567
+ async function launchDeepseekWithOrgx(prompt, deps = {}) {
14568
+ if (prompt.length === 0 || prompt.every((part) => !part.trim())) {
14569
+ throw new Error('Give DeepSeek a prompt, for example: orgx-wizard deepseek "What changed while I was away?"');
14570
+ }
14571
+ const runtime = inspectDeepseekRuntime(deps.runtimeRunner);
14572
+ if (!runtime.installed) {
14573
+ throw new Error("DeepSeek Harness was not found. Run orgx-wizard setup after installing DSH.");
14574
+ }
14575
+ if (!runtime.supported) {
14576
+ throw new Error(`DeepSeek Harness ${runtime.version ?? "unknown"} is not supported by this OrgX plugin.`);
14577
+ }
14578
+ const auth = await resolveFreshMcpAuth(deps);
14579
+ const childEnv = {
14580
+ ...deps.env ?? process.env,
14581
+ ORGX_MCP_ACCESS_TOKEN: auth.apiKey
14582
+ };
14583
+ delete childEnv.ORGX_API_KEY;
14584
+ const spawn2 = deps.spawn ?? spawnSync4;
14585
+ const result = spawn2(
14586
+ "dsh",
14587
+ ["--profile", DEEPSEEK_PROFILE, prompt.join(" ")],
14588
+ {
14589
+ env: childEnv,
14590
+ stdio: "inherit"
14591
+ }
14592
+ );
14593
+ if (result.error) throw result.error;
14594
+ return { status: result.status ?? 1 };
14595
+ }
14596
+
14033
14597
  // src/cli.ts
14034
14598
  var ICON = {
14035
14599
  ok: pc3.green("\u2713"),
@@ -14099,7 +14663,7 @@ function printSurfaceSummary(results) {
14099
14663
  ` ${ICON.skip} ${pc3.dim("No supported AI tools detected on this machine.")}`
14100
14664
  );
14101
14665
  console.log(
14102
- ` ${pc3.dim("\u2192")} ${pc3.dim("Install Claude, Cursor, Codex, VS Code, Windsurf, or Zed, then re-run setup.")}`
14666
+ ` ${pc3.dim("\u2192")} ${pc3.dim("Install Claude, Cursor, Codex, DeepSeek Harness, VS Code, Windsurf, or Zed, then re-run setup.")}`
14103
14667
  );
14104
14668
  return;
14105
14669
  }
@@ -14766,7 +15330,7 @@ function openPathInEditor(path) {
14766
15330
  if (!editor) {
14767
15331
  return false;
14768
15332
  }
14769
- const result = spawnSync3(editor, [path], {
15333
+ const result = spawnSync5(editor, [path], {
14770
15334
  shell: true,
14771
15335
  stdio: "inherit"
14772
15336
  });
@@ -15584,14 +16148,20 @@ async function promptOptionalCompanionPluginTargets(input) {
15584
16148
  return selection;
15585
16149
  }
15586
16150
  function printPluginSkillOwnershipNote(targets) {
15587
- if (!targets.some((target) => target === "cursor" || target === "claude" || target === "codex")) {
15588
- return;
16151
+ if (targets.includes("claude")) {
16152
+ console.log(
16153
+ ` ${ICON.skip} ${pc3.dim(
16154
+ "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."
16155
+ )}`
16156
+ );
16157
+ }
16158
+ if (targets.some((target) => target === "cursor" || target === "codex")) {
16159
+ console.log(
16160
+ ` ${ICON.skip} ${pc3.dim(
16161
+ "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."
16162
+ )}`
16163
+ );
15589
16164
  }
15590
- console.log(
15591
- ` ${ICON.skip} ${pc3.dim(
15592
- "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."
15593
- )}`
15594
- );
15595
16165
  }
15596
16166
  async function installSelectedCompanionPlugins(input) {
15597
16167
  if (input.targets.length === 0) {
@@ -15749,7 +16319,7 @@ async function main() {
15749
16319
  initializeWizardSentry();
15750
16320
  const program = new Command();
15751
16321
  program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
15752
- const pkgVersion = true ? "0.1.51" : void 0;
16322
+ const pkgVersion = true ? "0.1.55" : void 0;
15753
16323
  program.version(pkgVersion ?? "unknown", "-V, --version");
15754
16324
  program.hook("preAction", (_thisCommand, actionCommand) => {
15755
16325
  if (Boolean(actionCommand.optsWithGlobals().json)) return;
@@ -16052,6 +16622,10 @@ async function main() {
16052
16622
  }
16053
16623
  }
16054
16624
  });
16625
+ 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) => {
16626
+ const result = await launchDeepseekWithOrgx(prompt);
16627
+ if (result.status !== 0) process.exitCode = result.status;
16628
+ });
16055
16629
  async function runPkceLogin(opts = {}) {
16056
16630
  const spinner = createOrgxSpinner("Starting OrgX OAuth login");
16057
16631
  spinner.start();
@@ -16773,10 +17347,5 @@ main().catch(async (error) => {
16773
17347
  console.error(pc3.red(error instanceof Error ? error.message : String(error)));
16774
17348
  process.exitCode = 1;
16775
17349
  });
16776
-
16777
- // src/cli.ts?sentryDebugIdProxy=true
16778
- var cli_default = void 0;
16779
- export {
16780
- cli_default as default
16781
- };
16782
- //# sourceMappingURL=cli.js.map
17350
+ //# sourceMappingURL=cli.js.map
17351
+ //# debugId=707a7fe5-404e-5aec-9c75-30f0f5d859d9