@useorgx/wizard 0.1.52 → 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
@@ -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]="edb4168b-4102-5109-afd1-34d3193fbf8c")}catch(e){}}();
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){}}();
6
6
  import * as clack from "@clack/prompts";
7
- import { spawnSync as spawnSync3 } from "child_process";
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 mkdirSync2,
2129
- mkdtempSync,
2130
- readFileSync as readFileSync2,
2131
- readdirSync as readdirSync2,
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 dirname3, join as join3, relative } from "path";
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 join2 } from "path";
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 join2(extensionsDir, `${scope}.${skillId}.md`);
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 readdirSync(extensionsDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => {
2733
- 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);
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
- join2(claudeSkillsDir, skillName, relativePath),
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: ORGX_PLUGIN_GITHUB_REF,
3541
+ ref: ORGX_CLAUDE_PLUGIN_REF,
3154
3542
  include: [
3155
3543
  { localPath: ".claude-plugin", remotePath: ".claude-plugin" },
3156
- { localPath: "agents", remotePath: "agents" },
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
- join3(localPath, entry.name),
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: join3(localPath, entry.name),
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
- rmSync(path, { force: true, recursive: true });
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
- let changed = false;
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
- const bytes = await fetchRemoteBytes(file.sourceUrl, fetchImpl);
3409
- if (writeBytesIfChanged(join3(destinationRoot, file.localPath), bytes)) {
3410
- changed = true;
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
- mkdirSync2(dirname3(path), { recursive: true });
3426
- writeFileSync2(path, next, "utf8");
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: "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.",
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
- rmSync(path, { force: true });
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 extractClaudePluginNames(payload) {
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
- if (typeof entry.name === "string") return [entry.name];
3517
- if (typeof entry.id === "string") return [entry.id];
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: extractClaudePluginNames(result.stdout).includes(ORGX_CLAUDE_PLUGIN_NAME)
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 join3(paths.cursorPluginDir, ".cursor-plugin", "plugin.json");
3970
+ return join4(paths.cursorPluginDir, ".cursor-plugin", "plugin.json");
3624
3971
  }
3625
3972
  function cursorPluginMcpPath(paths) {
3626
- return join3(paths.cursorPluginDir, ".mcp.json");
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 ?? join3(CURSOR_DIR, "mcp.json");
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(dirname3(paths.cursorPluginDir)) || readTextIfExists(paths.cursorRulePath) !== null;
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 install = await runner("claude", [
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 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.`
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 = mkdtempSync(join3(tmpdir(), "orgx-wizard-openclaw-"));
3898
- 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`);
3899
4254
  try {
3900
- writeFileSync2(archivePath, tarballBytes);
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
- rmSync(tempRoot, { force: true, recursive: true });
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 statSync3 } from "fs";
5234
- 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";
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 statSync3(path);
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: [join4(input.home, ".agents", "skills")],
5260
- claude: [join4(input.home, ".claude", "skills"), join4(input.cwd, ".claude", "skills")],
5261
- 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")],
5262
5776
  opencode: [
5263
- join4(input.home, ".opencode", "skills"),
5264
- join4(input.home, ".config", "opencode", "skills"),
5265
- join4(input.home, "Library", "Application Support", "opencode", "skills"),
5266
- 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")
5267
5781
  ],
5268
5782
  workspace: [
5269
- join4(input.cwd, "skills"),
5270
- join4(input.cwd, ".agents", "skills"),
5271
- join4(input.cwd, ".orgx", "skills")
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 = join4(current, entry.name);
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} (${relative2(process.cwd(), candidate.path)})`,
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.52",
6214
+ release: "useorgx-wizard@0.1.55",
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 statSync4 } from "fs";
6419
- 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";
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 = join5(current, entry);
7099
+ const path = join6(current, entry);
6586
7100
  let stats;
6587
7101
  try {
6588
- stats = statSync4(path);
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 = statSync4(candidate.path);
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 = relative3(root, candidate.path);
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 statSync5 } from "fs";
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 join6, resolve } from "path";
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 statSync5(path);
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 = join6(current, entry);
7263
+ const path = join7(current, entry);
6750
7264
  const stats = safeStat2(path);
6751
7265
  if (!stats) continue;
6752
7266
  if (stats.isDirectory()) {
@@ -12982,22 +13496,22 @@ function buildWorkGraphHookReplayPatch(readResult) {
12982
13496
  }
12983
13497
 
12984
13498
  // src/lib/runtime-hooks.ts
12985
- import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "fs";
13499
+ import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
12986
13500
  import { homedir as homedir3 } from "os";
12987
- import { dirname as dirname4, join as join7 } from "path";
13501
+ import { dirname as dirname5, join as join8 } from "path";
12988
13502
  var HOOK_MARKER = "orgx-session-hook.mjs";
12989
13503
  var EMIT_HOOK_MARKER = "orgx-emit-execution-graph.mjs";
12990
13504
  var HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PermissionRequest", "Stop"];
12991
13505
  var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "SubagentStop", "Stop", "SessionEnd"];
12992
13506
  function defaultPaths(options = {}) {
12993
- const hookDir = join7(ORGX_WIZARD_CONFIG_HOME, "hooks");
13507
+ const hookDir = join8(ORGX_WIZARD_CONFIG_HOME, "hooks");
12994
13508
  return {
12995
- claudeSettingsPath: options.claudeSettingsPath ?? join7(CLAUDE_DIR, "settings.json"),
12996
- codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join7(CODEX_DIR, "config.toml"),
12997
- codexHooksPath: options.codexHooksPath ?? join7(CODEX_DIR, "hooks.json"),
12998
- hookScriptPath: options.hookScriptPath ?? join7(hookDir, HOOK_MARKER),
12999
- emitHookScriptPath: options.emitHookScriptPath ?? join7(hookDir, EMIT_HOOK_MARKER),
13000
- 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")
13001
13515
  };
13002
13516
  }
13003
13517
  function countJsonlLines(path) {
@@ -13379,7 +13893,7 @@ function installRuntimeHooks(targets, options = {}) {
13379
13893
  hookScript: false,
13380
13894
  emitHookScript: false
13381
13895
  };
13382
- mkdirSync3(dirname4(paths.hookScriptPath), { recursive: true, mode: 448 });
13896
+ mkdirSync4(dirname5(paths.hookScriptPath), { recursive: true, mode: 448 });
13383
13897
  const scriptContent = buildRuntimeHookScriptContent();
13384
13898
  if (readTextIfExists(paths.hookScriptPath) !== scriptContent) {
13385
13899
  const backup = backupExisting(paths.hookScriptPath, now);
@@ -13387,7 +13901,7 @@ function installRuntimeHooks(targets, options = {}) {
13387
13901
  writeTextFile(paths.hookScriptPath, scriptContent, { mode: 448 });
13388
13902
  changed.hookScript = true;
13389
13903
  }
13390
- mkdirSync3(dirname4(paths.emitHookScriptPath), { recursive: true, mode: 448 });
13904
+ mkdirSync4(dirname5(paths.emitHookScriptPath), { recursive: true, mode: 448 });
13391
13905
  const emitScriptContent = buildExecutionGraphEmitScriptContent();
13392
13906
  if (readTextIfExists(paths.emitHookScriptPath) !== emitScriptContent) {
13393
13907
  const backup = backupExisting(paths.emitHookScriptPath, now);
@@ -14013,6 +14527,73 @@ async function requestWorkloadDiagnosis(input, options = {}) {
14013
14527
  return parsed.data;
14014
14528
  }
14015
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
+
14016
14597
  // src/cli.ts
14017
14598
  var ICON = {
14018
14599
  ok: pc3.green("\u2713"),
@@ -14082,7 +14663,7 @@ function printSurfaceSummary(results) {
14082
14663
  ` ${ICON.skip} ${pc3.dim("No supported AI tools detected on this machine.")}`
14083
14664
  );
14084
14665
  console.log(
14085
- ` ${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.")}`
14086
14667
  );
14087
14668
  return;
14088
14669
  }
@@ -14749,7 +15330,7 @@ function openPathInEditor(path) {
14749
15330
  if (!editor) {
14750
15331
  return false;
14751
15332
  }
14752
- const result = spawnSync3(editor, [path], {
15333
+ const result = spawnSync5(editor, [path], {
14753
15334
  shell: true,
14754
15335
  stdio: "inherit"
14755
15336
  });
@@ -15567,14 +16148,20 @@ async function promptOptionalCompanionPluginTargets(input) {
15567
16148
  return selection;
15568
16149
  }
15569
16150
  function printPluginSkillOwnershipNote(targets) {
15570
- if (!targets.some((target) => target === "cursor" || target === "claude" || target === "codex")) {
15571
- 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
+ );
15572
16164
  }
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
16165
  }
15579
16166
  async function installSelectedCompanionPlugins(input) {
15580
16167
  if (input.targets.length === 0) {
@@ -15732,7 +16319,7 @@ async function main() {
15732
16319
  initializeWizardSentry();
15733
16320
  const program = new Command();
15734
16321
  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.52" : void 0;
16322
+ const pkgVersion = true ? "0.1.55" : void 0;
15736
16323
  program.version(pkgVersion ?? "unknown", "-V, --version");
15737
16324
  program.hook("preAction", (_thisCommand, actionCommand) => {
15738
16325
  if (Boolean(actionCommand.optsWithGlobals().json)) return;
@@ -16035,6 +16622,10 @@ async function main() {
16035
16622
  }
16036
16623
  }
16037
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
+ });
16038
16629
  async function runPkceLogin(opts = {}) {
16039
16630
  const spinner = createOrgxSpinner("Starting OrgX OAuth login");
16040
16631
  spinner.start();
@@ -16757,4 +17348,4 @@ main().catch(async (error) => {
16757
17348
  process.exitCode = 1;
16758
17349
  });
16759
17350
  //# sourceMappingURL=cli.js.map
16760
- //# debugId=edb4168b-4102-5109-afd1-34d3193fbf8c
17351
+ //# debugId=707a7fe5-404e-5aec-9c75-30f0f5d859d9