@useorgx/wizard 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/cli.js +252 -227
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -940,6 +940,7 @@ function parseOnboardingTask(value) {
|
|
|
940
940
|
...isNonEmptyString2(record.initiativeId) ? { initiativeId: record.initiativeId.trim() } : {},
|
|
941
941
|
...isNonEmptyString2(record.status) ? { status: record.status.trim() } : {},
|
|
942
942
|
title: record.title.trim(),
|
|
943
|
+
...isNonEmptyString2(record.workstreamId) ? { workstreamId: record.workstreamId.trim() } : {},
|
|
943
944
|
...isNonEmptyString2(record.workspaceId) ? { workspaceId: record.workspaceId.trim() } : {},
|
|
944
945
|
...isNonEmptyString2(record.workspaceName) ? { workspaceName: record.workspaceName.trim() } : {}
|
|
945
946
|
};
|
|
@@ -1045,6 +1046,9 @@ function getOrCreateWizardInstallationId(statePath = ORGX_WIZARD_STATE_PATH) {
|
|
|
1045
1046
|
writeWizardState(record, statePath);
|
|
1046
1047
|
return record.installationId;
|
|
1047
1048
|
}
|
|
1049
|
+
function clearWizardState(statePath = ORGX_WIZARD_STATE_PATH) {
|
|
1050
|
+
return deleteFileIfExists(statePath);
|
|
1051
|
+
}
|
|
1048
1052
|
|
|
1049
1053
|
// src/lib/agent-roster.ts
|
|
1050
1054
|
var AGENT_ROSTER_PROFILES = [
|
|
@@ -1239,39 +1243,6 @@ async function checkHostedMcpHealth() {
|
|
|
1239
1243
|
|
|
1240
1244
|
// src/lib/hosted-mcp-tool-check.ts
|
|
1241
1245
|
var DEFAULT_TOOL_NAME = "get_setup_status";
|
|
1242
|
-
function buildHeaders(apiKey, sessionId) {
|
|
1243
|
-
const headers = {
|
|
1244
|
-
Authorization: `Bearer ${apiKey}`,
|
|
1245
|
-
"Content-Type": "application/json",
|
|
1246
|
-
Accept: "application/json, text/event-stream"
|
|
1247
|
-
};
|
|
1248
|
-
if (sessionId) {
|
|
1249
|
-
headers["Mcp-Session-Id"] = sessionId;
|
|
1250
|
-
}
|
|
1251
|
-
return headers;
|
|
1252
|
-
}
|
|
1253
|
-
async function readJsonSafe(response) {
|
|
1254
|
-
const text2 = await response.text();
|
|
1255
|
-
if (!text2) return null;
|
|
1256
|
-
try {
|
|
1257
|
-
return JSON.parse(text2);
|
|
1258
|
-
} catch {
|
|
1259
|
-
return text2;
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
function readJsonRpcError(payload) {
|
|
1263
|
-
if (!payload || typeof payload !== "object") {
|
|
1264
|
-
return void 0;
|
|
1265
|
-
}
|
|
1266
|
-
const maybeError = payload.error;
|
|
1267
|
-
if (!maybeError || typeof maybeError !== "object") {
|
|
1268
|
-
return void 0;
|
|
1269
|
-
}
|
|
1270
|
-
return typeof maybeError.message === "string" ? maybeError.message : "Unknown MCP JSON-RPC error.";
|
|
1271
|
-
}
|
|
1272
|
-
function readSessionId(response) {
|
|
1273
|
-
return response.headers.get("mcp-session-id") ?? response.headers.get("Mcp-Session-Id") ?? void 0;
|
|
1274
|
-
}
|
|
1275
1246
|
async function checkHostedMcpToolAccess(options = {}, toolName = DEFAULT_TOOL_NAME) {
|
|
1276
1247
|
const auth = await resolveOrgxAuth(options);
|
|
1277
1248
|
if (!auth) {
|
|
@@ -1286,157 +1257,20 @@ async function checkHostedMcpToolAccess(options = {}, toolName = DEFAULT_TOOL_NA
|
|
|
1286
1257
|
details: []
|
|
1287
1258
|
};
|
|
1288
1259
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
capabilities: {}
|
|
1304
|
-
}
|
|
1305
|
-
}),
|
|
1306
|
-
signal: AbortSignal.timeout(1e4)
|
|
1307
|
-
});
|
|
1308
|
-
const initializePayload = await readJsonSafe(initializeResponse);
|
|
1309
|
-
const initializeError = readJsonRpcError(initializePayload);
|
|
1310
|
-
const sessionId = readSessionId(initializeResponse);
|
|
1311
|
-
if (!initializeResponse.ok) {
|
|
1312
|
-
return {
|
|
1313
|
-
configured: true,
|
|
1314
|
-
ok: false,
|
|
1315
|
-
skipped: false,
|
|
1316
|
-
source: auth.source,
|
|
1317
|
-
toolName,
|
|
1318
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1319
|
-
baseUrl: auth.baseUrl,
|
|
1320
|
-
initializeStatus: initializeResponse.status,
|
|
1321
|
-
error: `MCP initialize failed with HTTP ${initializeResponse.status}.`,
|
|
1322
|
-
details: [`auth source: ${auth.source}`],
|
|
1323
|
-
response: initializePayload
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
if (initializeError) {
|
|
1327
|
-
return {
|
|
1328
|
-
configured: true,
|
|
1329
|
-
ok: false,
|
|
1330
|
-
skipped: false,
|
|
1331
|
-
source: auth.source,
|
|
1332
|
-
toolName,
|
|
1333
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1334
|
-
baseUrl: auth.baseUrl,
|
|
1335
|
-
initializeStatus: initializeResponse.status,
|
|
1336
|
-
error: `MCP initialize returned JSON-RPC error: ${initializeError}`,
|
|
1337
|
-
details: [`auth source: ${auth.source}`],
|
|
1338
|
-
response: initializePayload
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
if (!sessionId) {
|
|
1342
|
-
return {
|
|
1343
|
-
configured: true,
|
|
1344
|
-
ok: false,
|
|
1345
|
-
skipped: false,
|
|
1346
|
-
source: auth.source,
|
|
1347
|
-
toolName,
|
|
1348
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1349
|
-
baseUrl: auth.baseUrl,
|
|
1350
|
-
initializeStatus: initializeResponse.status,
|
|
1351
|
-
error: "MCP initialize succeeded but no Mcp-Session-Id header was returned.",
|
|
1352
|
-
details: [`auth source: ${auth.source}`],
|
|
1353
|
-
response: initializePayload
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
const callResponse = await fetch(ORGX_HOSTED_MCP_URL, {
|
|
1357
|
-
method: "POST",
|
|
1358
|
-
headers: buildHeaders(auth.apiKey, sessionId),
|
|
1359
|
-
body: JSON.stringify({
|
|
1360
|
-
jsonrpc: "2.0",
|
|
1361
|
-
id: 2,
|
|
1362
|
-
method: "tools/call",
|
|
1363
|
-
params: {
|
|
1364
|
-
name: toolName,
|
|
1365
|
-
arguments: {}
|
|
1366
|
-
}
|
|
1367
|
-
}),
|
|
1368
|
-
signal: AbortSignal.timeout(1e4)
|
|
1369
|
-
});
|
|
1370
|
-
const callPayload = await readJsonSafe(callResponse);
|
|
1371
|
-
const callError = readJsonRpcError(callPayload);
|
|
1372
|
-
if (!callResponse.ok) {
|
|
1373
|
-
return {
|
|
1374
|
-
configured: true,
|
|
1375
|
-
ok: false,
|
|
1376
|
-
skipped: false,
|
|
1377
|
-
source: auth.source,
|
|
1378
|
-
toolName,
|
|
1379
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1380
|
-
baseUrl: auth.baseUrl,
|
|
1381
|
-
initializeStatus: initializeResponse.status,
|
|
1382
|
-
callStatus: callResponse.status,
|
|
1383
|
-
error: `MCP tool call failed with HTTP ${callResponse.status}.`,
|
|
1384
|
-
details: [
|
|
1385
|
-
`auth source: ${auth.source}`,
|
|
1386
|
-
`session established: ${sessionId}`
|
|
1387
|
-
],
|
|
1388
|
-
response: callPayload
|
|
1389
|
-
};
|
|
1390
|
-
}
|
|
1391
|
-
if (callError) {
|
|
1392
|
-
return {
|
|
1393
|
-
configured: true,
|
|
1394
|
-
ok: false,
|
|
1395
|
-
skipped: false,
|
|
1396
|
-
source: auth.source,
|
|
1397
|
-
toolName,
|
|
1398
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1399
|
-
baseUrl: auth.baseUrl,
|
|
1400
|
-
initializeStatus: initializeResponse.status,
|
|
1401
|
-
callStatus: callResponse.status,
|
|
1402
|
-
error: `MCP tool call returned JSON-RPC error: ${callError}`,
|
|
1403
|
-
details: [
|
|
1404
|
-
`auth source: ${auth.source}`,
|
|
1405
|
-
`session established: ${sessionId}`
|
|
1406
|
-
],
|
|
1407
|
-
response: callPayload
|
|
1408
|
-
};
|
|
1409
|
-
}
|
|
1410
|
-
return {
|
|
1411
|
-
configured: true,
|
|
1412
|
-
ok: true,
|
|
1413
|
-
skipped: false,
|
|
1414
|
-
source: auth.source,
|
|
1415
|
-
toolName,
|
|
1416
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1417
|
-
baseUrl: auth.baseUrl,
|
|
1418
|
-
initializeStatus: initializeResponse.status,
|
|
1419
|
-
callStatus: callResponse.status,
|
|
1420
|
-
details: [
|
|
1421
|
-
`auth source: ${auth.source}`,
|
|
1422
|
-
`session established: ${sessionId}`,
|
|
1423
|
-
`tool call: ${toolName}`
|
|
1424
|
-
],
|
|
1425
|
-
response: callPayload
|
|
1426
|
-
};
|
|
1427
|
-
} catch (error) {
|
|
1428
|
-
return {
|
|
1429
|
-
configured: true,
|
|
1430
|
-
ok: false,
|
|
1431
|
-
skipped: false,
|
|
1432
|
-
source: auth.source,
|
|
1433
|
-
toolName,
|
|
1434
|
-
url: ORGX_HOSTED_MCP_URL,
|
|
1435
|
-
baseUrl: auth.baseUrl,
|
|
1436
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1437
|
-
details: [`auth source: ${auth.source}`]
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1260
|
+
return {
|
|
1261
|
+
configured: true,
|
|
1262
|
+
ok: false,
|
|
1263
|
+
skipped: true,
|
|
1264
|
+
source: auth.source,
|
|
1265
|
+
toolName,
|
|
1266
|
+
url: ORGX_HOSTED_MCP_URL,
|
|
1267
|
+
baseUrl: auth.baseUrl,
|
|
1268
|
+
error: "Hosted OrgX MCP uses OAuth; API-key tool verification is skipped.",
|
|
1269
|
+
details: [
|
|
1270
|
+
`auth source: ${auth.source}`,
|
|
1271
|
+
"Hosted OrgX MCP connectors complete OAuth during client setup, so the wizard cannot preflight tools with an oxk_ API key."
|
|
1272
|
+
]
|
|
1273
|
+
};
|
|
1440
1274
|
}
|
|
1441
1275
|
|
|
1442
1276
|
// src/lib/npm-registry-health.ts
|
|
@@ -1633,7 +1467,7 @@ async function getCurrentWorkspace(options = {}) {
|
|
|
1633
1467
|
}
|
|
1634
1468
|
return workspace;
|
|
1635
1469
|
}
|
|
1636
|
-
if (response.status === 404) {
|
|
1470
|
+
if (response.status === 401 || response.status === 404) {
|
|
1637
1471
|
const workspaces = await listWorkspaces(options);
|
|
1638
1472
|
return workspaces[0] ?? null;
|
|
1639
1473
|
}
|
|
@@ -2334,7 +2168,10 @@ function buildChatgptManualStatus(detection, authHint) {
|
|
|
2334
2168
|
"Manual step: in ChatGPT desktop developer mode, add a custom connector pointing at the hosted OrgX MCP URL."
|
|
2335
2169
|
);
|
|
2336
2170
|
details.push(
|
|
2337
|
-
"
|
|
2171
|
+
"ChatGPT completes OAuth during connector setup; the wizard cannot preflight hosted MCP tools with an oxk_ API key."
|
|
2172
|
+
);
|
|
2173
|
+
details.push(
|
|
2174
|
+
"After connecting ChatGPT, run `orgx-wizard doctor` to verify hosted MCP health from this machine."
|
|
2338
2175
|
);
|
|
2339
2176
|
} else {
|
|
2340
2177
|
details.push(
|
|
@@ -2369,7 +2206,7 @@ function buildChatgptAddResult(path, authHint, toolCheck) {
|
|
|
2369
2206
|
message: `Run \`${AUTH_SETUP_HINT}\` or \`${AUTH_SET_KEY_HINT}\` first, then add ${ORGX_HOSTED_MCP_URL} as a custom connector in ChatGPT developer mode.`
|
|
2370
2207
|
};
|
|
2371
2208
|
}
|
|
2372
|
-
if (!toolCheck
|
|
2209
|
+
if (toolCheck && !toolCheck.ok && !toolCheck.skipped) {
|
|
2373
2210
|
const failure = toolCheck?.error ?? "hosted MCP verification did not complete.";
|
|
2374
2211
|
return {
|
|
2375
2212
|
name: "chatgpt",
|
|
@@ -2382,7 +2219,7 @@ function buildChatgptAddResult(path, authHint, toolCheck) {
|
|
|
2382
2219
|
name: "chatgpt",
|
|
2383
2220
|
changed: false,
|
|
2384
2221
|
...path ? { path } : {},
|
|
2385
|
-
message: `OrgX auth
|
|
2222
|
+
message: `OrgX auth is ready via ${formatAuthHintSource(authHint)}. Add ${ORGX_HOSTED_MCP_URL} as a custom connector in ChatGPT developer mode; ChatGPT will complete the OAuth flow there. Then run \`${DOCTOR_HINT}\` to verify hosted MCP health from this machine.`
|
|
2386
2223
|
};
|
|
2387
2224
|
}
|
|
2388
2225
|
function buildChatgptRemoveResult(path) {
|
|
@@ -2520,8 +2357,7 @@ async function addAutomatedSurface(name) {
|
|
|
2520
2357
|
if (!authHint) {
|
|
2521
2358
|
return buildChatgptAddResult(path, null);
|
|
2522
2359
|
}
|
|
2523
|
-
|
|
2524
|
-
return buildChatgptAddResult(path, authHint, toolCheck);
|
|
2360
|
+
return buildChatgptAddResult(path, authHint);
|
|
2525
2361
|
}
|
|
2526
2362
|
default:
|
|
2527
2363
|
return {
|
|
@@ -2827,6 +2663,8 @@ var FOUNDER_DEMO_ARTIFACT_TYPE = "document";
|
|
|
2827
2663
|
var FOUNDER_DEMO_ARTIFACT_DESCRIPTION = "Live founder demo generated by @useorgx/wizard after workspace bootstrap completed.";
|
|
2828
2664
|
var ONBOARDING_TASK_TITLE = "Complete OrgX onboarding";
|
|
2829
2665
|
var ONBOARDING_TASK_SUMMARY = "Starter onboarding task created by @useorgx/wizard so the first workspace has a clear follow-up after setup.";
|
|
2666
|
+
var ONBOARDING_WORKSTREAM_TITLE = "OrgX onboarding";
|
|
2667
|
+
var ONBOARDING_WORKSTREAM_SUMMARY = "Starter onboarding workstream created by @useorgx/wizard so the first workspace has a home for setup follow-up tasks.";
|
|
2830
2668
|
function parseResponseBody3(text2) {
|
|
2831
2669
|
if (!text2) {
|
|
2832
2670
|
return null;
|
|
@@ -2910,6 +2748,15 @@ function parseTask(payload) {
|
|
|
2910
2748
|
...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
|
|
2911
2749
|
};
|
|
2912
2750
|
}
|
|
2751
|
+
function parseWorkstream(payload) {
|
|
2752
|
+
const entity = extractEntity(payload);
|
|
2753
|
+
const id = typeof entity.id === "string" ? entity.id.trim() : "";
|
|
2754
|
+
const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
|
|
2755
|
+
if (!id || !title) {
|
|
2756
|
+
throw new Error("OrgX returned an incomplete workstream payload.");
|
|
2757
|
+
}
|
|
2758
|
+
return { id, title };
|
|
2759
|
+
}
|
|
2913
2760
|
function toDemoInitiativeRecord(artifact, decision, initiative, liveUrl, workspace) {
|
|
2914
2761
|
return {
|
|
2915
2762
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2927,13 +2774,14 @@ function toDemoInitiativeRecord(artifact, decision, initiative, liveUrl, workspa
|
|
|
2927
2774
|
workspaceName: workspace.name
|
|
2928
2775
|
};
|
|
2929
2776
|
}
|
|
2930
|
-
function toOnboardingTaskRecord(task, workspace,
|
|
2777
|
+
function toOnboardingTaskRecord(task, workspace, options = {}) {
|
|
2931
2778
|
return {
|
|
2932
2779
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2933
2780
|
id: task.id,
|
|
2934
|
-
...initiativeId ? { initiativeId } : {},
|
|
2781
|
+
...options.initiativeId ? { initiativeId: options.initiativeId } : {},
|
|
2935
2782
|
...task.status ? { status: task.status } : {},
|
|
2936
2783
|
title: task.title,
|
|
2784
|
+
...options.workstreamId ? { workstreamId: options.workstreamId } : {},
|
|
2937
2785
|
workspaceId: workspace.id,
|
|
2938
2786
|
workspaceName: workspace.name
|
|
2939
2787
|
};
|
|
@@ -3112,14 +2960,33 @@ async function ensureOnboardingTask(workspace, options = {}) {
|
|
|
3112
2960
|
...existingRecord.status ? { status: existingRecord.status } : {}
|
|
3113
2961
|
};
|
|
3114
2962
|
}
|
|
2963
|
+
const initiativeId = options.initiativeId?.trim();
|
|
2964
|
+
if (!initiativeId) {
|
|
2965
|
+
throw new Error(
|
|
2966
|
+
"Starter onboarding task requires an initiative context. Re-run setup with the founder preset or create an initiative before requesting onboarding tasks."
|
|
2967
|
+
);
|
|
2968
|
+
}
|
|
2969
|
+
const workstream = await createEntity(
|
|
2970
|
+
"workstream",
|
|
2971
|
+
{
|
|
2972
|
+
initiative_id: initiativeId,
|
|
2973
|
+
status: "active",
|
|
2974
|
+
summary: ONBOARDING_WORKSTREAM_SUMMARY,
|
|
2975
|
+
title: ONBOARDING_WORKSTREAM_TITLE,
|
|
2976
|
+
workspace_id: workspace.id
|
|
2977
|
+
},
|
|
2978
|
+
parseWorkstream,
|
|
2979
|
+
options
|
|
2980
|
+
);
|
|
3115
2981
|
const task = await createEntity(
|
|
3116
2982
|
"task",
|
|
3117
2983
|
{
|
|
2984
|
+
initiative_id: initiativeId,
|
|
3118
2985
|
status: "todo",
|
|
3119
2986
|
summary: ONBOARDING_TASK_SUMMARY,
|
|
3120
2987
|
title: ONBOARDING_TASK_TITLE,
|
|
3121
|
-
|
|
3122
|
-
|
|
2988
|
+
workstream_id: workstream.id,
|
|
2989
|
+
workspace_id: workspace.id
|
|
3123
2990
|
},
|
|
3124
2991
|
parseTask,
|
|
3125
2992
|
options
|
|
@@ -3127,7 +2994,10 @@ async function ensureOnboardingTask(workspace, options = {}) {
|
|
|
3127
2994
|
updateWizardState(
|
|
3128
2995
|
(current) => ({
|
|
3129
2996
|
...current,
|
|
3130
|
-
onboardingTask: toOnboardingTaskRecord(task, workspace,
|
|
2997
|
+
onboardingTask: toOnboardingTaskRecord(task, workspace, {
|
|
2998
|
+
initiativeId,
|
|
2999
|
+
workstreamId: workstream.id
|
|
3000
|
+
})
|
|
3131
3001
|
}),
|
|
3132
3002
|
options.statePath
|
|
3133
3003
|
);
|
|
@@ -3414,7 +3284,7 @@ import {
|
|
|
3414
3284
|
} from "fs";
|
|
3415
3285
|
import { tmpdir } from "os";
|
|
3416
3286
|
import { dirname as dirname3, join as join3, relative } from "path";
|
|
3417
|
-
var DEFAULT_ORGX_PLUGIN_TARGETS = ["claude", "codex", "openclaw"];
|
|
3287
|
+
var DEFAULT_ORGX_PLUGIN_TARGETS = ["cursor", "claude", "codex", "openclaw"];
|
|
3418
3288
|
var ORGX_PLUGIN_GITHUB_OWNER = "useorgx";
|
|
3419
3289
|
var ORGX_PLUGIN_GITHUB_REF = "main";
|
|
3420
3290
|
var ORGX_CLAUDE_PLUGIN_NAME = "orgx-claude-code-plugin";
|
|
@@ -3453,7 +3323,8 @@ function defaultPluginPaths() {
|
|
|
3453
3323
|
claudeMarketplaceManifestPath: CLAUDE_MANAGED_MARKETPLACE_MANIFEST_PATH,
|
|
3454
3324
|
claudePluginDir: CLAUDE_MANAGED_PLUGIN_DIR,
|
|
3455
3325
|
codexMarketplacePath: CODEX_MARKETPLACE_PATH,
|
|
3456
|
-
codexPluginDir: CODEX_ORGX_PLUGIN_DIR
|
|
3326
|
+
codexPluginDir: CODEX_ORGX_PLUGIN_DIR,
|
|
3327
|
+
cursorRulePath: CURSOR_ORGX_RULE_PATH
|
|
3457
3328
|
};
|
|
3458
3329
|
}
|
|
3459
3330
|
function resolvePluginPaths(paths = {}) {
|
|
@@ -3873,6 +3744,32 @@ async function getOpenclawInstallState(runner) {
|
|
|
3873
3744
|
installed: extractOpenclawPluginIds(result.stdout).includes(ORGX_OPENCLAW_PLUGIN_ID)
|
|
3874
3745
|
};
|
|
3875
3746
|
}
|
|
3747
|
+
function buildCursorStatus(paths) {
|
|
3748
|
+
const existingRules = readTextIfExists(paths.cursorRulePath);
|
|
3749
|
+
const available = detectSurface("cursor").detected || existingRules !== null;
|
|
3750
|
+
if (existingRules === CURSOR_RULES_CONTENT) {
|
|
3751
|
+
return {
|
|
3752
|
+
target: "cursor",
|
|
3753
|
+
available: true,
|
|
3754
|
+
installed: true,
|
|
3755
|
+
message: "Cursor OrgX rules are installed."
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
if (existingRules !== null) {
|
|
3759
|
+
return {
|
|
3760
|
+
target: "cursor",
|
|
3761
|
+
available: true,
|
|
3762
|
+
installed: false,
|
|
3763
|
+
message: "Cursor OrgX rules file exists, but differs from the managed rules."
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
return {
|
|
3767
|
+
target: "cursor",
|
|
3768
|
+
available,
|
|
3769
|
+
installed: false,
|
|
3770
|
+
message: available ? "Cursor is available and ready for OrgX rules install." : "Cursor was not detected."
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3876
3773
|
async function buildClaudeStatus(paths, runner) {
|
|
3877
3774
|
const state = await getClaudeInstallState(runner);
|
|
3878
3775
|
if (state.installed) {
|
|
@@ -3988,6 +3885,30 @@ async function resolveOpenclawTarball(fetchImpl) {
|
|
|
3988
3885
|
version: latestVersion
|
|
3989
3886
|
};
|
|
3990
3887
|
}
|
|
3888
|
+
function installCursorPlugin(paths) {
|
|
3889
|
+
const existingRules = readTextIfExists(paths.cursorRulePath);
|
|
3890
|
+
const available = detectSurface("cursor").detected || existingRules !== null;
|
|
3891
|
+
if (!available) {
|
|
3892
|
+
return {
|
|
3893
|
+
target: "cursor",
|
|
3894
|
+
changed: false,
|
|
3895
|
+
message: "Cursor is not available on this machine."
|
|
3896
|
+
};
|
|
3897
|
+
}
|
|
3898
|
+
if (existingRules === CURSOR_RULES_CONTENT) {
|
|
3899
|
+
return {
|
|
3900
|
+
target: "cursor",
|
|
3901
|
+
changed: false,
|
|
3902
|
+
message: "Cursor OrgX rules are already installed."
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3905
|
+
writeTextFile(paths.cursorRulePath, CURSOR_RULES_CONTENT);
|
|
3906
|
+
return {
|
|
3907
|
+
target: "cursor",
|
|
3908
|
+
changed: true,
|
|
3909
|
+
message: "Installed the managed Cursor OrgX rules."
|
|
3910
|
+
};
|
|
3911
|
+
}
|
|
3991
3912
|
async function installClaudePlugin(paths, fetchImpl, runner) {
|
|
3992
3913
|
const state = await getClaudeInstallState(runner);
|
|
3993
3914
|
if (!state.available) {
|
|
@@ -4094,6 +4015,29 @@ async function installOpenclawPlugin(fetchImpl, runner) {
|
|
|
4094
4015
|
message: `Installed OpenClaw plugin ${ORGX_OPENCLAW_PLUGIN_ID} from ${ORGX_OPENCLAW_PLUGIN_PACKAGE_NAME}@${version}.`
|
|
4095
4016
|
};
|
|
4096
4017
|
}
|
|
4018
|
+
function uninstallCursorPlugin(paths) {
|
|
4019
|
+
const existingRules = readTextIfExists(paths.cursorRulePath);
|
|
4020
|
+
if (existingRules === null) {
|
|
4021
|
+
return {
|
|
4022
|
+
target: "cursor",
|
|
4023
|
+
changed: false,
|
|
4024
|
+
message: "Cursor OrgX rules were not installed."
|
|
4025
|
+
};
|
|
4026
|
+
}
|
|
4027
|
+
if (existingRules !== CURSOR_RULES_CONTENT) {
|
|
4028
|
+
return {
|
|
4029
|
+
target: "cursor",
|
|
4030
|
+
changed: false,
|
|
4031
|
+
message: "Cursor rules file differs from the managed OrgX rules, so it was left in place."
|
|
4032
|
+
};
|
|
4033
|
+
}
|
|
4034
|
+
const changed = deleteFileIfExists(paths.cursorRulePath);
|
|
4035
|
+
return {
|
|
4036
|
+
target: "cursor",
|
|
4037
|
+
changed,
|
|
4038
|
+
message: changed ? "Removed the managed Cursor OrgX rules." : "Cursor OrgX rules were not installed."
|
|
4039
|
+
};
|
|
4040
|
+
}
|
|
4097
4041
|
async function uninstallClaudePlugin(paths, runner) {
|
|
4098
4042
|
const state = await getClaudeInstallState(runner);
|
|
4099
4043
|
let changed = false;
|
|
@@ -4189,6 +4133,7 @@ async function listOrgxPluginStatuses(options = {}) {
|
|
|
4189
4133
|
const paths = resolvePluginPaths(options.paths);
|
|
4190
4134
|
const runner = resolveCommandRunner(options.commandRunner);
|
|
4191
4135
|
return await Promise.all([
|
|
4136
|
+
buildCursorStatus(paths),
|
|
4192
4137
|
buildClaudeStatus(paths, runner),
|
|
4193
4138
|
buildCodexStatus(paths, runner),
|
|
4194
4139
|
buildOpenclawStatus(runner)
|
|
@@ -4205,6 +4150,9 @@ async function installOrgxPlugins(options = {}) {
|
|
|
4205
4150
|
const results = [];
|
|
4206
4151
|
for (const target of targets) {
|
|
4207
4152
|
switch (target) {
|
|
4153
|
+
case "cursor":
|
|
4154
|
+
results.push(installCursorPlugin(paths));
|
|
4155
|
+
break;
|
|
4208
4156
|
case "claude":
|
|
4209
4157
|
results.push(await installClaudePlugin(paths, fetchImpl, runner));
|
|
4210
4158
|
break;
|
|
@@ -4225,6 +4173,9 @@ async function uninstallOrgxPlugins(options = {}) {
|
|
|
4225
4173
|
const results = [];
|
|
4226
4174
|
for (const target of targets) {
|
|
4227
4175
|
switch (target) {
|
|
4176
|
+
case "cursor":
|
|
4177
|
+
results.push(uninstallCursorPlugin(paths));
|
|
4178
|
+
break;
|
|
4228
4179
|
case "claude":
|
|
4229
4180
|
results.push(await uninstallClaudePlugin(paths, runner));
|
|
4230
4181
|
break;
|
|
@@ -4691,6 +4642,8 @@ function formatAuthSource(source) {
|
|
|
4691
4642
|
}
|
|
4692
4643
|
function formatPluginTargetLabel(target) {
|
|
4693
4644
|
switch (target) {
|
|
4645
|
+
case "cursor":
|
|
4646
|
+
return "Cursor rules";
|
|
4694
4647
|
case "claude":
|
|
4695
4648
|
return "Claude Code";
|
|
4696
4649
|
case "codex":
|
|
@@ -4735,6 +4688,16 @@ function printPluginMutationReport(report) {
|
|
|
4735
4688
|
);
|
|
4736
4689
|
}
|
|
4737
4690
|
}
|
|
4691
|
+
async function printPluginStatusSection() {
|
|
4692
|
+
const spinner = createOrgxSpinner("Checking OrgX plugin and Cursor rules status");
|
|
4693
|
+
spinner.start();
|
|
4694
|
+
const statuses = await listOrgxPluginStatuses();
|
|
4695
|
+
spinner.succeed("OrgX plugin and Cursor rules status checked");
|
|
4696
|
+
console.log("");
|
|
4697
|
+
console.log(pc3.dim(" plugins"));
|
|
4698
|
+
printPluginStatusReport(statuses);
|
|
4699
|
+
return statuses;
|
|
4700
|
+
}
|
|
4738
4701
|
function printSkillInstallReport(report) {
|
|
4739
4702
|
for (const write of report.writes) {
|
|
4740
4703
|
const icon = write.changed ? ICON.ok : ICON.skip;
|
|
@@ -4837,8 +4800,9 @@ async function textPrompt(input) {
|
|
|
4837
4800
|
}
|
|
4838
4801
|
async function multiselectPrompt(input) {
|
|
4839
4802
|
const promptInput = {
|
|
4840
|
-
message: input.message
|
|
4803
|
+
message: `${input.message} ${pc3.dim("Space selects items; Enter continues.")}`,
|
|
4841
4804
|
options: input.options,
|
|
4805
|
+
...input.initialValues ? { initialValues: input.initialValues } : {},
|
|
4842
4806
|
...input.required !== void 0 ? { required: input.required } : {}
|
|
4843
4807
|
};
|
|
4844
4808
|
return normalizePromptResult(await clack.multiselect(promptInput));
|
|
@@ -4943,8 +4907,9 @@ async function maybeConfigureOptionalWorkspaceAddOns(input) {
|
|
|
4943
4907
|
return "skipped";
|
|
4944
4908
|
}
|
|
4945
4909
|
const existingState = readWizardState();
|
|
4910
|
+
const effectiveInitiativeId = input.initiativeId?.trim() || (existingState?.demoInitiative?.workspaceId === input.workspace.id ? existingState.demoInitiative.id : void 0);
|
|
4946
4911
|
const hasOnboardingTask = existingState?.onboardingTask?.workspaceId === input.workspace.id;
|
|
4947
|
-
if (!hasOnboardingTask) {
|
|
4912
|
+
if (!hasOnboardingTask && effectiveInitiativeId) {
|
|
4948
4913
|
const onboardingChoice = await selectPrompt({
|
|
4949
4914
|
message: `Create a starter onboarding task for ${input.workspace.name}?`,
|
|
4950
4915
|
options: [
|
|
@@ -4957,34 +4922,40 @@ async function maybeConfigureOptionalWorkspaceAddOns(input) {
|
|
|
4957
4922
|
return "cancelled";
|
|
4958
4923
|
}
|
|
4959
4924
|
if (onboardingChoice === "yes") {
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4925
|
+
try {
|
|
4926
|
+
const task = await ensureOnboardingTask(input.workspace, {
|
|
4927
|
+
initiativeId: effectiveInitiativeId
|
|
4928
|
+
});
|
|
4929
|
+
console.log(` ${ICON.ok} ${pc3.green("onboarding")} ${pc3.bold(task.title)}`);
|
|
4930
|
+
await safeTrackWizardTelemetry(
|
|
4931
|
+
"onboarding_task_created",
|
|
4932
|
+
buildOnboardingTaskTelemetryProperties(
|
|
4933
|
+
{
|
|
4934
|
+
created: true,
|
|
4935
|
+
hasInitiative: true,
|
|
4936
|
+
task
|
|
4937
|
+
},
|
|
4938
|
+
{
|
|
4939
|
+
command: input.telemetry?.command ?? "setup",
|
|
4940
|
+
...input.telemetry?.preset ? { preset: input.telemetry.preset } : {}
|
|
4941
|
+
}
|
|
4942
|
+
)
|
|
4943
|
+
);
|
|
4944
|
+
} catch (error) {
|
|
4945
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4946
|
+
console.log(` ${ICON.warn} ${pc3.yellow("onboarding")} ${pc3.dim(message)}`);
|
|
4947
|
+
}
|
|
4978
4948
|
}
|
|
4979
4949
|
}
|
|
4980
4950
|
const refreshedState = readWizardState();
|
|
4981
4951
|
const hasAgentRoster = refreshedState?.agentRoster?.workspaceId === input.workspace.id;
|
|
4982
4952
|
if (!hasAgentRoster) {
|
|
4983
4953
|
const rosterChoice = await selectPrompt({
|
|
4954
|
+
initialValue: "default",
|
|
4984
4955
|
message: `Set up an OrgX agent roster for ${input.workspace.name}?`,
|
|
4985
4956
|
options: [
|
|
4986
|
-
{ value: "
|
|
4987
|
-
{ value: "
|
|
4957
|
+
{ value: "default", label: "Install the full default roster", hint: "recommended" },
|
|
4958
|
+
{ value: "guided", label: "Choose agents and domains" },
|
|
4988
4959
|
{ value: "no", label: "Skip roster setup" }
|
|
4989
4960
|
]
|
|
4990
4961
|
});
|
|
@@ -5039,7 +5010,13 @@ async function promptOptionalCompanionPluginTargets(input) {
|
|
|
5039
5010
|
if (!input.interactive) {
|
|
5040
5011
|
return [];
|
|
5041
5012
|
}
|
|
5042
|
-
|
|
5013
|
+
let statuses = input.statuses;
|
|
5014
|
+
if (!statuses) {
|
|
5015
|
+
const spinner = createOrgxSpinner("Checking optional OrgX plugin and Cursor rules status");
|
|
5016
|
+
spinner.start();
|
|
5017
|
+
statuses = await listOrgxPluginStatuses();
|
|
5018
|
+
spinner.succeed("Optional OrgX plugin and Cursor rules status checked");
|
|
5019
|
+
}
|
|
5043
5020
|
const installable = statuses.filter((status) => status.available && !status.installed);
|
|
5044
5021
|
if (installable.length === 0) {
|
|
5045
5022
|
return [];
|
|
@@ -5090,7 +5067,8 @@ async function installSelectedCompanionPlugins(input) {
|
|
|
5090
5067
|
}
|
|
5091
5068
|
async function maybeInstallOptionalCompanionPlugins(input) {
|
|
5092
5069
|
const selection = await promptOptionalCompanionPluginTargets({
|
|
5093
|
-
interactive: input.interactive
|
|
5070
|
+
interactive: input.interactive,
|
|
5071
|
+
...input.statuses ? { statuses: input.statuses } : {}
|
|
5094
5072
|
});
|
|
5095
5073
|
if (selection === "cancelled") {
|
|
5096
5074
|
return "cancelled";
|
|
@@ -5178,7 +5156,7 @@ function printDoctorReport(report, assessment) {
|
|
|
5178
5156
|
async function main() {
|
|
5179
5157
|
const program = new Command();
|
|
5180
5158
|
program.name("orgx-wizard").description("One-line CLI onboarding for OrgX surfaces.").showHelpAfterError();
|
|
5181
|
-
const pkgVersion = true ? "0.1.
|
|
5159
|
+
const pkgVersion = true ? "0.1.10" : void 0;
|
|
5182
5160
|
program.version(pkgVersion ?? "unknown", "-V, --version");
|
|
5183
5161
|
program.hook("preAction", () => {
|
|
5184
5162
|
console.log(renderBanner(pkgVersion));
|
|
@@ -5289,6 +5267,7 @@ async function main() {
|
|
|
5289
5267
|
const results = await setupDetectedSurfaces();
|
|
5290
5268
|
spinner.succeed("Detected surfaces configured");
|
|
5291
5269
|
printMutationResults(results);
|
|
5270
|
+
const pluginStatuses = await printPluginStatusSection();
|
|
5292
5271
|
await safeTrackWizardTelemetry("mcp_injected", {
|
|
5293
5272
|
changed_count: results.filter((result) => result.changed).length,
|
|
5294
5273
|
preset: "standard",
|
|
@@ -5377,6 +5356,7 @@ async function main() {
|
|
|
5377
5356
|
}
|
|
5378
5357
|
const pluginInstallResult = await maybeInstallOptionalCompanionPlugins({
|
|
5379
5358
|
interactive,
|
|
5359
|
+
statuses: pluginStatuses,
|
|
5380
5360
|
telemetry: { command: "setup", preset: "standard" }
|
|
5381
5361
|
});
|
|
5382
5362
|
if (pluginInstallResult === "cancelled") {
|
|
@@ -5547,6 +5527,51 @@ async function main() {
|
|
|
5547
5527
|
);
|
|
5548
5528
|
}
|
|
5549
5529
|
});
|
|
5530
|
+
program.command("uninstall").description("Remove OrgX-managed surfaces, companion plugins/rules, auth, and wizard state from this machine.").option("--keep-auth", "Keep the wizard-local saved OrgX API key.").option("--keep-state", "Keep wizard-local setup state.").option("--skip-plugins", "Skip companion plugin and Cursor rules removal.").option("--skip-surfaces", "Skip MCP surface config removal.").action(async (options) => {
|
|
5531
|
+
await safeTrackWizardTelemetry("wizard_uninstalled", {
|
|
5532
|
+
keep_auth: Boolean(options.keepAuth),
|
|
5533
|
+
keep_state: Boolean(options.keepState),
|
|
5534
|
+
skip_plugins: Boolean(options.skipPlugins),
|
|
5535
|
+
skip_surfaces: Boolean(options.skipSurfaces)
|
|
5536
|
+
});
|
|
5537
|
+
console.log(pc3.bold("Removing OrgX wizard-managed configuration"));
|
|
5538
|
+
if (options.skipSurfaces) {
|
|
5539
|
+
console.log(` ${ICON.skip} ${pc3.bold("surfaces".padEnd(10))} ${pc3.dim("skipped")}`);
|
|
5540
|
+
} else {
|
|
5541
|
+
console.log("");
|
|
5542
|
+
console.log(pc3.dim(" surfaces"));
|
|
5543
|
+
const surfaceResults = removeSurface(["all"]);
|
|
5544
|
+
printMutationResults(surfaceResults);
|
|
5545
|
+
}
|
|
5546
|
+
if (options.skipPlugins) {
|
|
5547
|
+
console.log(` ${ICON.skip} ${pc3.bold("plugins".padEnd(12))} ${pc3.dim("skipped")}`);
|
|
5548
|
+
} else {
|
|
5549
|
+
console.log("");
|
|
5550
|
+
console.log(pc3.dim(" plugins"));
|
|
5551
|
+
const spinner = createOrgxSpinner("Removing OrgX companion plugins and rules");
|
|
5552
|
+
spinner.start();
|
|
5553
|
+
const pluginReport = await uninstallOrgxPlugins({ targets: ["all"] });
|
|
5554
|
+
spinner.succeed("OrgX companion plugins and rules processed");
|
|
5555
|
+
printPluginMutationReport(pluginReport);
|
|
5556
|
+
}
|
|
5557
|
+
console.log("");
|
|
5558
|
+
if (options.keepAuth) {
|
|
5559
|
+
console.log(` ${ICON.skip} ${pc3.bold("auth".padEnd(12))} ${pc3.dim("kept")}`);
|
|
5560
|
+
} else {
|
|
5561
|
+
const removedAuth = await clearWizardAuth();
|
|
5562
|
+
const state = removedAuth ? pc3.green("updated ") : pc3.dim("unchanged");
|
|
5563
|
+
const message = removedAuth ? "Removed the wizard-local OrgX API key." : "No wizard-local OrgX API key was stored.";
|
|
5564
|
+
console.log(` ${removedAuth ? ICON.ok : ICON.skip} ${pc3.bold("auth".padEnd(12))} ${state} ${pc3.dim(message)}`);
|
|
5565
|
+
}
|
|
5566
|
+
if (options.keepState) {
|
|
5567
|
+
console.log(` ${ICON.skip} ${pc3.bold("state".padEnd(12))} ${pc3.dim("kept")}`);
|
|
5568
|
+
} else {
|
|
5569
|
+
const removedState = clearWizardState();
|
|
5570
|
+
const state = removedState ? pc3.green("updated ") : pc3.dim("unchanged");
|
|
5571
|
+
const message = removedState ? "Removed wizard-local setup state." : "No wizard-local setup state was stored.";
|
|
5572
|
+
console.log(` ${removedState ? ICON.ok : ICON.skip} ${pc3.bold("state".padEnd(12))} ${state} ${pc3.dim(message)}`);
|
|
5573
|
+
}
|
|
5574
|
+
});
|
|
5550
5575
|
const surface = program.command("surface").description("Manage supported OrgX surfaces.");
|
|
5551
5576
|
surface.command("list").description("Show supported surfaces and their current status.").action(() => {
|
|
5552
5577
|
printSurfaceTable(listSurfaceStatuses());
|
|
@@ -5568,15 +5593,15 @@ async function main() {
|
|
|
5568
5593
|
const results = removeMcpSurface(names);
|
|
5569
5594
|
printMutationResults(results);
|
|
5570
5595
|
});
|
|
5571
|
-
const plugins = program.command("plugins").description("Install or remove companion OrgX plugins for Claude Code, Codex, and OpenClaw.");
|
|
5596
|
+
const plugins = program.command("plugins").description("Install or remove Cursor rules and companion OrgX plugins for Claude Code, Codex, and OpenClaw.");
|
|
5572
5597
|
plugins.command("list").description("Show companion plugin availability and install status.").action(async () => {
|
|
5573
|
-
const spinner = createOrgxSpinner("Checking
|
|
5598
|
+
const spinner = createOrgxSpinner("Checking OrgX plugin and Cursor rules status");
|
|
5574
5599
|
spinner.start();
|
|
5575
5600
|
const statuses = await listOrgxPluginStatuses();
|
|
5576
|
-
spinner.
|
|
5601
|
+
spinner.succeed("OrgX plugin and Cursor rules status checked");
|
|
5577
5602
|
printPluginStatusReport(statuses);
|
|
5578
5603
|
});
|
|
5579
|
-
plugins.command("add").description("Install OrgX companion plugins into Claude Code, Codex,
|
|
5604
|
+
plugins.command("add").description("Install Cursor OrgX rules or companion plugins into Claude Code, Codex, and OpenClaw.").argument("[targets...]", "cursor, claude, codex, openclaw, or all", ["all"]).action(async (targets) => {
|
|
5580
5605
|
const spinner = createOrgxSpinner("Installing OrgX companion plugins");
|
|
5581
5606
|
spinner.start();
|
|
5582
5607
|
const report = await installOrgxPlugins({ targets });
|
|
@@ -5590,7 +5615,7 @@ async function main() {
|
|
|
5590
5615
|
target_count: report.results.length
|
|
5591
5616
|
});
|
|
5592
5617
|
});
|
|
5593
|
-
plugins.command("remove").description("Uninstall managed OrgX companion plugins from Claude Code, Codex,
|
|
5618
|
+
plugins.command("remove").description("Uninstall managed Cursor OrgX rules or companion plugins from Claude Code, Codex, and OpenClaw.").argument("[targets...]", "cursor, claude, codex, openclaw, or all", ["all"]).action(async (targets) => {
|
|
5594
5619
|
const spinner = createOrgxSpinner("Removing OrgX companion plugins");
|
|
5595
5620
|
spinner.start();
|
|
5596
5621
|
const report = await uninstallOrgxPlugins({ targets });
|