@codecell-germany/company-agent-wiki-skill 0.1.0 → 0.1.2
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 +130 -135
- package/dist/index.js +507 -91
- package/dist/installer.js +2 -1
- package/knowledge/ARCHITECTURE.md +19 -1
- package/knowledge/KNOWN_LIMITATIONS.md +3 -1
- package/knowledge/RELEASE_CHECKLIST.md +19 -0
- package/package.json +1 -1
- package/skills/company-agent-wiki-cli/SKILL.md +22 -7
- package/skills/company-agent-wiki-cli/references/agent-onboarding.md +7 -0
- package/skills/company-agent-wiki-cli/references/command-cheatsheet.md +6 -0
- package/skills/company-agent-wiki-cli/references/overview.md +11 -7
- package/skills/company-agent-wiki-cli/references/workspace-first-run.md +12 -1
package/dist/index.js
CHANGED
|
@@ -1189,8 +1189,8 @@ var require_command = __commonJS({
|
|
|
1189
1189
|
"node_modules/commander/lib/command.js"(exports2) {
|
|
1190
1190
|
var EventEmitter = require("node:events").EventEmitter;
|
|
1191
1191
|
var childProcess = require("node:child_process");
|
|
1192
|
-
var
|
|
1193
|
-
var
|
|
1192
|
+
var path9 = require("node:path");
|
|
1193
|
+
var fs9 = require("node:fs");
|
|
1194
1194
|
var process2 = require("node:process");
|
|
1195
1195
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1196
1196
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2184,7 +2184,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2184
2184
|
* @param {string} subcommandName
|
|
2185
2185
|
*/
|
|
2186
2186
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2187
|
-
if (
|
|
2187
|
+
if (fs9.existsSync(executableFile)) return;
|
|
2188
2188
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2189
2189
|
const executableMissing = `'${executableFile}' does not exist
|
|
2190
2190
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2202,11 +2202,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2202
2202
|
let launchWithNode = false;
|
|
2203
2203
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2204
2204
|
function findFile(baseDir, baseName) {
|
|
2205
|
-
const localBin =
|
|
2206
|
-
if (
|
|
2207
|
-
if (sourceExt.includes(
|
|
2205
|
+
const localBin = path9.resolve(baseDir, baseName);
|
|
2206
|
+
if (fs9.existsSync(localBin)) return localBin;
|
|
2207
|
+
if (sourceExt.includes(path9.extname(baseName))) return void 0;
|
|
2208
2208
|
const foundExt = sourceExt.find(
|
|
2209
|
-
(ext) =>
|
|
2209
|
+
(ext) => fs9.existsSync(`${localBin}${ext}`)
|
|
2210
2210
|
);
|
|
2211
2211
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2212
2212
|
return void 0;
|
|
@@ -2218,21 +2218,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2218
2218
|
if (this._scriptPath) {
|
|
2219
2219
|
let resolvedScriptPath;
|
|
2220
2220
|
try {
|
|
2221
|
-
resolvedScriptPath =
|
|
2221
|
+
resolvedScriptPath = fs9.realpathSync(this._scriptPath);
|
|
2222
2222
|
} catch {
|
|
2223
2223
|
resolvedScriptPath = this._scriptPath;
|
|
2224
2224
|
}
|
|
2225
|
-
executableDir =
|
|
2226
|
-
|
|
2225
|
+
executableDir = path9.resolve(
|
|
2226
|
+
path9.dirname(resolvedScriptPath),
|
|
2227
2227
|
executableDir
|
|
2228
2228
|
);
|
|
2229
2229
|
}
|
|
2230
2230
|
if (executableDir) {
|
|
2231
2231
|
let localFile = findFile(executableDir, executableFile);
|
|
2232
2232
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2233
|
-
const legacyName =
|
|
2233
|
+
const legacyName = path9.basename(
|
|
2234
2234
|
this._scriptPath,
|
|
2235
|
-
|
|
2235
|
+
path9.extname(this._scriptPath)
|
|
2236
2236
|
);
|
|
2237
2237
|
if (legacyName !== this._name) {
|
|
2238
2238
|
localFile = findFile(
|
|
@@ -2243,7 +2243,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2243
2243
|
}
|
|
2244
2244
|
executableFile = localFile || executableFile;
|
|
2245
2245
|
}
|
|
2246
|
-
launchWithNode = sourceExt.includes(
|
|
2246
|
+
launchWithNode = sourceExt.includes(path9.extname(executableFile));
|
|
2247
2247
|
let proc;
|
|
2248
2248
|
if (process2.platform !== "win32") {
|
|
2249
2249
|
if (launchWithNode) {
|
|
@@ -3158,7 +3158,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3158
3158
|
* @return {Command}
|
|
3159
3159
|
*/
|
|
3160
3160
|
nameFromFilename(filename) {
|
|
3161
|
-
this._name =
|
|
3161
|
+
this._name = path9.basename(filename, path9.extname(filename));
|
|
3162
3162
|
return this;
|
|
3163
3163
|
}
|
|
3164
3164
|
/**
|
|
@@ -3172,9 +3172,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3172
3172
|
* @param {string} [path]
|
|
3173
3173
|
* @return {(string|null|Command)}
|
|
3174
3174
|
*/
|
|
3175
|
-
executableDir(
|
|
3176
|
-
if (
|
|
3177
|
-
this._executableDir =
|
|
3175
|
+
executableDir(path10) {
|
|
3176
|
+
if (path10 === void 0) return this._executableDir;
|
|
3177
|
+
this._executableDir = path10;
|
|
3178
3178
|
return this;
|
|
3179
3179
|
}
|
|
3180
3180
|
/**
|
|
@@ -6823,7 +6823,7 @@ var require_parse = __commonJS({
|
|
|
6823
6823
|
var require_gray_matter = __commonJS({
|
|
6824
6824
|
"node_modules/gray-matter/index.js"(exports2, module2) {
|
|
6825
6825
|
"use strict";
|
|
6826
|
-
var
|
|
6826
|
+
var fs9 = require("fs");
|
|
6827
6827
|
var sections = require_section_matter();
|
|
6828
6828
|
var defaults = require_defaults();
|
|
6829
6829
|
var stringify = require_stringify();
|
|
@@ -6907,7 +6907,7 @@ var require_gray_matter = __commonJS({
|
|
|
6907
6907
|
return stringify(file, data, options3);
|
|
6908
6908
|
};
|
|
6909
6909
|
matter2.read = function(filepath, options3) {
|
|
6910
|
-
const str2 =
|
|
6910
|
+
const str2 = fs9.readFileSync(filepath, "utf8");
|
|
6911
6911
|
const file = matter2(str2, options3);
|
|
6912
6912
|
file.path = filepath;
|
|
6913
6913
|
return file;
|
|
@@ -6936,8 +6936,8 @@ var require_gray_matter = __commonJS({
|
|
|
6936
6936
|
});
|
|
6937
6937
|
|
|
6938
6938
|
// src/index.ts
|
|
6939
|
-
var
|
|
6940
|
-
var
|
|
6939
|
+
var import_node_fs8 = __toESM(require("node:fs"));
|
|
6940
|
+
var import_node_path8 = __toESM(require("node:path"));
|
|
6941
6941
|
|
|
6942
6942
|
// node_modules/commander/esm.mjs
|
|
6943
6943
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -6963,8 +6963,10 @@ var WORKSPACE_INTERNAL_DIR = ".company-agent-wiki";
|
|
|
6963
6963
|
var WORKSPACE_CONFIG_FILE = "workspace.json";
|
|
6964
6964
|
var INDEX_DB_FILE = "index.sqlite";
|
|
6965
6965
|
var INDEX_MANIFEST_FILE = "index-manifest.json";
|
|
6966
|
+
var GLOBAL_REGISTRY_DIR_NAME = "company-agent-wiki";
|
|
6967
|
+
var GLOBAL_REGISTRY_FILE = "workspaces.json";
|
|
6966
6968
|
var WORKSPACE_LAYOUT_VERSION = 1;
|
|
6967
|
-
var CLI_SCHEMA_VERSION = "2026-04-
|
|
6969
|
+
var CLI_SCHEMA_VERSION = "2026-04-13";
|
|
6968
6970
|
var INDEX_SCHEMA_VERSION = 1;
|
|
6969
6971
|
var DEFAULT_MANAGED_ROOT_ID = "canonical";
|
|
6970
6972
|
var DEFAULT_MANAGED_ROOT_PATH = "knowledge/canonical";
|
|
@@ -6979,6 +6981,7 @@ var EXIT_CODES = {
|
|
|
6979
6981
|
notFound: 6,
|
|
6980
6982
|
git: 7,
|
|
6981
6983
|
sqliteLocked: 8,
|
|
6984
|
+
workspaceBusy: 9,
|
|
6982
6985
|
runtime: 10
|
|
6983
6986
|
};
|
|
6984
6987
|
|
|
@@ -7139,8 +7142,8 @@ function getGitDiff(filePath, baseRef, compareRef) {
|
|
|
7139
7142
|
}
|
|
7140
7143
|
|
|
7141
7144
|
// src/lib/indexer.ts
|
|
7142
|
-
var
|
|
7143
|
-
var
|
|
7145
|
+
var import_node_fs5 = __toESM(require("node:fs"));
|
|
7146
|
+
var import_node_path6 = __toESM(require("node:path"));
|
|
7144
7147
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"));
|
|
7145
7148
|
|
|
7146
7149
|
// src/lib/fs-utils.ts
|
|
@@ -7159,6 +7162,7 @@ function writeJsonFile(targetPath, value) {
|
|
|
7159
7162
|
}
|
|
7160
7163
|
function writeJsonAtomic(targetPath, value) {
|
|
7161
7164
|
const tempPath = `${targetPath}.tmp`;
|
|
7165
|
+
ensureDir(import_node_path2.default.dirname(targetPath));
|
|
7162
7166
|
writeJsonFile(tempPath, value);
|
|
7163
7167
|
import_node_fs2.default.renameSync(tempPath, targetPath);
|
|
7164
7168
|
}
|
|
@@ -7340,8 +7344,29 @@ var import_node_path4 = __toESM(require("node:path"));
|
|
|
7340
7344
|
function getDefaultCodexHome() {
|
|
7341
7345
|
return process.env.CODEX_HOME || import_node_path4.default.join(import_node_os.default.homedir(), ".codex");
|
|
7342
7346
|
}
|
|
7347
|
+
function getGlobalRegistryDir() {
|
|
7348
|
+
const explicit = process.env.COMPANY_AGENT_WIKI_CONFIG_HOME;
|
|
7349
|
+
if (explicit?.trim()) {
|
|
7350
|
+
return import_node_path4.default.resolve(explicit);
|
|
7351
|
+
}
|
|
7352
|
+
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
|
7353
|
+
return import_node_path4.default.join(import_node_os.default.tmpdir(), GLOBAL_REGISTRY_DIR_NAME, "vitest");
|
|
7354
|
+
}
|
|
7355
|
+
if (process.platform === "darwin") {
|
|
7356
|
+
return import_node_path4.default.join(import_node_os.default.homedir(), "Library", "Application Support", GLOBAL_REGISTRY_DIR_NAME);
|
|
7357
|
+
}
|
|
7358
|
+
if (process.platform === "win32") {
|
|
7359
|
+
const roaming = process.env.APPDATA || import_node_path4.default.join(import_node_os.default.homedir(), "AppData", "Roaming");
|
|
7360
|
+
return import_node_path4.default.join(roaming, GLOBAL_REGISTRY_DIR_NAME);
|
|
7361
|
+
}
|
|
7362
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || import_node_path4.default.join(import_node_os.default.homedir(), ".config");
|
|
7363
|
+
return import_node_path4.default.join(xdgConfig, GLOBAL_REGISTRY_DIR_NAME);
|
|
7364
|
+
}
|
|
7365
|
+
function getGlobalRegistryPath() {
|
|
7366
|
+
return import_node_path4.default.join(getGlobalRegistryDir(), GLOBAL_REGISTRY_FILE);
|
|
7367
|
+
}
|
|
7343
7368
|
function resolveWorkspacePaths(workspaceRoot) {
|
|
7344
|
-
const absoluteRoot =
|
|
7369
|
+
const absoluteRoot = normalizeWorkspaceRootPath(workspaceRoot);
|
|
7345
7370
|
const internalDir = import_node_path4.default.join(absoluteRoot, WORKSPACE_INTERNAL_DIR);
|
|
7346
7371
|
return {
|
|
7347
7372
|
workspaceRoot: absoluteRoot,
|
|
@@ -7367,6 +7392,160 @@ function detectWorkspaceRoot(startDir = process.cwd()) {
|
|
|
7367
7392
|
current = parent;
|
|
7368
7393
|
}
|
|
7369
7394
|
}
|
|
7395
|
+
function createDefaultGlobalRegistry() {
|
|
7396
|
+
return {
|
|
7397
|
+
schemaVersion: WORKSPACE_LAYOUT_VERSION,
|
|
7398
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7399
|
+
workspaces: []
|
|
7400
|
+
};
|
|
7401
|
+
}
|
|
7402
|
+
function normalizeWorkspaceRootPath(candidatePath) {
|
|
7403
|
+
const resolved = import_node_path4.default.resolve(candidatePath);
|
|
7404
|
+
try {
|
|
7405
|
+
return import_node_fs3.default.realpathSync.native ? import_node_fs3.default.realpathSync.native(resolved) : import_node_fs3.default.realpathSync(resolved);
|
|
7406
|
+
} catch {
|
|
7407
|
+
return resolved;
|
|
7408
|
+
}
|
|
7409
|
+
}
|
|
7410
|
+
function loadGlobalWorkspaceRegistry() {
|
|
7411
|
+
const registryPath = getGlobalRegistryPath();
|
|
7412
|
+
if (!fileExists(registryPath)) {
|
|
7413
|
+
return createDefaultGlobalRegistry();
|
|
7414
|
+
}
|
|
7415
|
+
const raw = readJsonFile(registryPath);
|
|
7416
|
+
const registry = createDefaultGlobalRegistry();
|
|
7417
|
+
registry.schemaVersion = raw.schemaVersion || registry.schemaVersion;
|
|
7418
|
+
registry.updatedAt = raw.updatedAt || registry.updatedAt;
|
|
7419
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
7420
|
+
for (const entry of raw.workspaces || []) {
|
|
7421
|
+
const normalizedPath = normalizeWorkspaceRootPath(entry.path);
|
|
7422
|
+
if (!fileExists(resolveWorkspacePaths(normalizedPath).configPath)) {
|
|
7423
|
+
continue;
|
|
7424
|
+
}
|
|
7425
|
+
const normalizedEntry = {
|
|
7426
|
+
workspaceId: entry.workspaceId,
|
|
7427
|
+
path: normalizedPath,
|
|
7428
|
+
label: entry.label || import_node_path4.default.basename(normalizedPath),
|
|
7429
|
+
registeredAt: entry.registeredAt,
|
|
7430
|
+
lastUsedAt: entry.lastUsedAt,
|
|
7431
|
+
source: entry.source
|
|
7432
|
+
};
|
|
7433
|
+
const existing = deduped.get(normalizedPath);
|
|
7434
|
+
if (!existing || existing.lastUsedAt < normalizedEntry.lastUsedAt) {
|
|
7435
|
+
deduped.set(normalizedPath, normalizedEntry);
|
|
7436
|
+
}
|
|
7437
|
+
}
|
|
7438
|
+
registry.workspaces = Array.from(deduped.values()).sort((left, right) => left.label.localeCompare(right.label));
|
|
7439
|
+
if (raw.defaultWorkspace) {
|
|
7440
|
+
const normalizedDefault = normalizeWorkspaceRootPath(raw.defaultWorkspace);
|
|
7441
|
+
if (deduped.has(normalizedDefault)) {
|
|
7442
|
+
registry.defaultWorkspace = normalizedDefault;
|
|
7443
|
+
}
|
|
7444
|
+
}
|
|
7445
|
+
const serializedRaw = JSON.stringify(raw);
|
|
7446
|
+
const serializedNormalized = JSON.stringify(registry);
|
|
7447
|
+
if (serializedRaw !== serializedNormalized) {
|
|
7448
|
+
saveGlobalWorkspaceRegistry(registry);
|
|
7449
|
+
}
|
|
7450
|
+
return registry;
|
|
7451
|
+
}
|
|
7452
|
+
function saveGlobalWorkspaceRegistry(registry) {
|
|
7453
|
+
writeJsonAtomic(getGlobalRegistryPath(), registry);
|
|
7454
|
+
}
|
|
7455
|
+
function buildRegisteredWorkspace(workspaceRoot, source) {
|
|
7456
|
+
const resolvedRoot = normalizeWorkspaceRootPath(workspaceRoot);
|
|
7457
|
+
const config = loadWorkspaceConfig(resolvedRoot);
|
|
7458
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7459
|
+
return {
|
|
7460
|
+
workspaceId: config.workspaceId,
|
|
7461
|
+
path: resolvedRoot,
|
|
7462
|
+
label: import_node_path4.default.basename(resolvedRoot),
|
|
7463
|
+
registeredAt: now,
|
|
7464
|
+
lastUsedAt: now,
|
|
7465
|
+
source
|
|
7466
|
+
};
|
|
7467
|
+
}
|
|
7468
|
+
function registerWorkspaceGlobally(workspaceRoot, options3) {
|
|
7469
|
+
const resolvedRoot = import_node_path4.default.resolve(workspaceRoot);
|
|
7470
|
+
const nextEntry = buildRegisteredWorkspace(resolvedRoot, options3?.source || "manual");
|
|
7471
|
+
const registry = loadGlobalWorkspaceRegistry();
|
|
7472
|
+
const existing = registry.workspaces.find((item) => item.path === resolvedRoot);
|
|
7473
|
+
if (existing) {
|
|
7474
|
+
existing.workspaceId = nextEntry.workspaceId;
|
|
7475
|
+
existing.label = nextEntry.label;
|
|
7476
|
+
existing.lastUsedAt = nextEntry.lastUsedAt;
|
|
7477
|
+
existing.source = nextEntry.source;
|
|
7478
|
+
} else {
|
|
7479
|
+
registry.workspaces.push(nextEntry);
|
|
7480
|
+
}
|
|
7481
|
+
if (options3?.setDefault || !registry.defaultWorkspace) {
|
|
7482
|
+
registry.defaultWorkspace = resolvedRoot;
|
|
7483
|
+
}
|
|
7484
|
+
registry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7485
|
+
saveGlobalWorkspaceRegistry(registry);
|
|
7486
|
+
return registry.workspaces.find((item) => item.path === resolvedRoot) || nextEntry;
|
|
7487
|
+
}
|
|
7488
|
+
function rememberWorkspaceGlobally(workspaceRoot, options3) {
|
|
7489
|
+
const configPath = resolveWorkspacePaths(workspaceRoot).configPath;
|
|
7490
|
+
if (!fileExists(configPath)) {
|
|
7491
|
+
return void 0;
|
|
7492
|
+
}
|
|
7493
|
+
try {
|
|
7494
|
+
return registerWorkspaceGlobally(workspaceRoot, options3);
|
|
7495
|
+
} catch {
|
|
7496
|
+
return void 0;
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
function listRegisteredWorkspaces() {
|
|
7500
|
+
const registry = loadGlobalWorkspaceRegistry();
|
|
7501
|
+
return {
|
|
7502
|
+
registryPath: getGlobalRegistryPath(),
|
|
7503
|
+
defaultWorkspace: registry.defaultWorkspace,
|
|
7504
|
+
workspaces: registry.workspaces.map((item) => ({
|
|
7505
|
+
...item,
|
|
7506
|
+
exists: fileExists(resolveWorkspacePaths(item.path).configPath)
|
|
7507
|
+
}))
|
|
7508
|
+
};
|
|
7509
|
+
}
|
|
7510
|
+
function resolveWorkspaceSelection(startDir = process.cwd()) {
|
|
7511
|
+
const registryPath = getGlobalRegistryPath();
|
|
7512
|
+
const cwdWorkspace = detectWorkspaceRoot(startDir);
|
|
7513
|
+
if (cwdWorkspace) {
|
|
7514
|
+
rememberWorkspaceGlobally(cwdWorkspace, { setDefault: true, source: "detected" });
|
|
7515
|
+
return {
|
|
7516
|
+
workspaceRoot: cwdWorkspace,
|
|
7517
|
+
source: "cwd",
|
|
7518
|
+
registryPath,
|
|
7519
|
+
defaultWorkspace: loadGlobalWorkspaceRegistry().defaultWorkspace
|
|
7520
|
+
};
|
|
7521
|
+
}
|
|
7522
|
+
const registry = loadGlobalWorkspaceRegistry();
|
|
7523
|
+
const existingWorkspaces = registry.workspaces.filter((item) => fileExists(resolveWorkspacePaths(item.path).configPath));
|
|
7524
|
+
const defaultWorkspace = registry.defaultWorkspace;
|
|
7525
|
+
if (defaultWorkspace && fileExists(resolveWorkspacePaths(defaultWorkspace).configPath)) {
|
|
7526
|
+
rememberWorkspaceGlobally(defaultWorkspace, { setDefault: true, source: "runtime" });
|
|
7527
|
+
return {
|
|
7528
|
+
workspaceRoot: defaultWorkspace,
|
|
7529
|
+
source: "global-default",
|
|
7530
|
+
registryPath,
|
|
7531
|
+
defaultWorkspace
|
|
7532
|
+
};
|
|
7533
|
+
}
|
|
7534
|
+
if (existingWorkspaces.length === 1) {
|
|
7535
|
+
const onlyWorkspace = existingWorkspaces[0].path;
|
|
7536
|
+
rememberWorkspaceGlobally(onlyWorkspace, { setDefault: true, source: "runtime" });
|
|
7537
|
+
return {
|
|
7538
|
+
workspaceRoot: onlyWorkspace,
|
|
7539
|
+
source: "single-registered",
|
|
7540
|
+
registryPath,
|
|
7541
|
+
defaultWorkspace: onlyWorkspace
|
|
7542
|
+
};
|
|
7543
|
+
}
|
|
7544
|
+
return {
|
|
7545
|
+
registryPath,
|
|
7546
|
+
defaultWorkspace
|
|
7547
|
+
};
|
|
7548
|
+
}
|
|
7370
7549
|
function templateWorkspaceReadme() {
|
|
7371
7550
|
return `# Private Company Knowledge Workspace
|
|
7372
7551
|
|
|
@@ -7734,6 +7913,7 @@ function setupWorkspace(options3) {
|
|
|
7734
7913
|
}
|
|
7735
7914
|
}
|
|
7736
7915
|
}
|
|
7916
|
+
registerWorkspaceGlobally(paths.workspaceRoot, { setDefault: true, source: "setup" });
|
|
7737
7917
|
return {
|
|
7738
7918
|
workspaceRoot: paths.workspaceRoot,
|
|
7739
7919
|
configPath: paths.configPath,
|
|
@@ -7743,7 +7923,8 @@ function setupWorkspace(options3) {
|
|
|
7743
7923
|
`company-agent-wiki-cli doctor --workspace ${paths.workspaceRoot} --json`,
|
|
7744
7924
|
`company-agent-wiki-cli index rebuild --workspace ${paths.workspaceRoot} --json`,
|
|
7745
7925
|
`company-agent-wiki-cli verify --workspace ${paths.workspaceRoot} --json`,
|
|
7746
|
-
`company-agent-wiki-cli serve --workspace ${paths.workspaceRoot} --port 4187
|
|
7926
|
+
`company-agent-wiki-cli serve --workspace ${paths.workspaceRoot} --port 4187`,
|
|
7927
|
+
"Other agents can now discover this workspace automatically via the global workspace registry."
|
|
7747
7928
|
]
|
|
7748
7929
|
};
|
|
7749
7930
|
}
|
|
@@ -7776,6 +7957,7 @@ function addRoot(workspaceRoot, rootDefinition) {
|
|
|
7776
7957
|
};
|
|
7777
7958
|
config.roots.push(root);
|
|
7778
7959
|
saveWorkspaceConfig(workspaceRoot, config);
|
|
7960
|
+
rememberWorkspaceGlobally(workspaceRoot, { setDefault: true, source: "runtime" });
|
|
7779
7961
|
return root;
|
|
7780
7962
|
}
|
|
7781
7963
|
function listRoots(workspaceRoot) {
|
|
@@ -7797,6 +7979,8 @@ function doctor(workspaceRoot) {
|
|
|
7797
7979
|
const codexBinDir = import_node_path4.default.join(codexHome, "bin");
|
|
7798
7980
|
const codexShimPath = import_node_path4.default.join(codexBinDir, CLI_NAME);
|
|
7799
7981
|
const pathEntries = (process.env.PATH || "").split(import_node_path4.default.delimiter).filter(Boolean);
|
|
7982
|
+
const registryPath = getGlobalRegistryPath();
|
|
7983
|
+
const registry = loadGlobalWorkspaceRegistry();
|
|
7800
7984
|
checks.push({
|
|
7801
7985
|
name: "workspace-root",
|
|
7802
7986
|
ok: isDirectory(paths.workspaceRoot),
|
|
@@ -7822,6 +8006,16 @@ function doctor(workspaceRoot) {
|
|
|
7822
8006
|
ok: pathEntries.includes(codexBinDir),
|
|
7823
8007
|
message: pathEntries.includes(codexBinDir) ? `Codex bin directory is available in PATH: ${codexBinDir}` : `Codex bin directory is not in PATH: ${codexBinDir}`
|
|
7824
8008
|
});
|
|
8009
|
+
checks.push({
|
|
8010
|
+
name: "global-workspace-registry",
|
|
8011
|
+
ok: fileExists(registryPath),
|
|
8012
|
+
message: fileExists(registryPath) ? `Global workspace registry found: ${registryPath}` : `Global workspace registry missing: ${registryPath}`
|
|
8013
|
+
});
|
|
8014
|
+
checks.push({
|
|
8015
|
+
name: "global-default-workspace",
|
|
8016
|
+
ok: typeof registry.defaultWorkspace === "string" && fileExists(resolveWorkspacePaths(registry.defaultWorkspace).configPath),
|
|
8017
|
+
message: typeof registry.defaultWorkspace === "string" ? `Global default workspace: ${registry.defaultWorkspace}` : "No global default workspace registered yet."
|
|
8018
|
+
});
|
|
7825
8019
|
if (fileExists(paths.configPath)) {
|
|
7826
8020
|
const config = loadWorkspaceConfig(workspaceRoot);
|
|
7827
8021
|
for (const root of config.roots) {
|
|
@@ -7849,6 +8043,121 @@ function doctor(workspaceRoot) {
|
|
|
7849
8043
|
};
|
|
7850
8044
|
}
|
|
7851
8045
|
|
|
8046
|
+
// src/lib/write-lock.ts
|
|
8047
|
+
var import_node_fs4 = __toESM(require("node:fs"));
|
|
8048
|
+
var import_node_path5 = __toESM(require("node:path"));
|
|
8049
|
+
var LOCK_FILE_NAME = "write.lock";
|
|
8050
|
+
var LOCK_WAIT_TIMEOUT_MS = 6e4;
|
|
8051
|
+
var LOCK_POLL_INTERVAL_MS = 125;
|
|
8052
|
+
var LOCK_STALE_AFTER_MS = 10 * 6e4;
|
|
8053
|
+
function sleepMs(durationMs) {
|
|
8054
|
+
const shared = new SharedArrayBuffer(4);
|
|
8055
|
+
const array = new Int32Array(shared);
|
|
8056
|
+
Atomics.wait(array, 0, 0, durationMs);
|
|
8057
|
+
}
|
|
8058
|
+
function getLockPath(workspaceRoot) {
|
|
8059
|
+
return import_node_path5.default.join(import_node_path5.default.resolve(workspaceRoot), WORKSPACE_INTERNAL_DIR, LOCK_FILE_NAME);
|
|
8060
|
+
}
|
|
8061
|
+
function readLockPayload(lockPath) {
|
|
8062
|
+
if (!fileExists(lockPath)) {
|
|
8063
|
+
return void 0;
|
|
8064
|
+
}
|
|
8065
|
+
try {
|
|
8066
|
+
return readJsonFile(lockPath);
|
|
8067
|
+
} catch {
|
|
8068
|
+
return void 0;
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
8071
|
+
function isProcessAlive(pid) {
|
|
8072
|
+
if (!pid || pid <= 0) {
|
|
8073
|
+
return false;
|
|
8074
|
+
}
|
|
8075
|
+
try {
|
|
8076
|
+
process.kill(pid, 0);
|
|
8077
|
+
return true;
|
|
8078
|
+
} catch (error) {
|
|
8079
|
+
const code = error.code;
|
|
8080
|
+
return code !== "ESRCH";
|
|
8081
|
+
}
|
|
8082
|
+
}
|
|
8083
|
+
function canBreakLock(payload) {
|
|
8084
|
+
if (!payload) {
|
|
8085
|
+
return true;
|
|
8086
|
+
}
|
|
8087
|
+
const acquiredAt = Date.parse(payload.acquiredAt);
|
|
8088
|
+
const ageMs = Number.isNaN(acquiredAt) ? Number.POSITIVE_INFINITY : Date.now() - acquiredAt;
|
|
8089
|
+
if (ageMs > LOCK_STALE_AFTER_MS) {
|
|
8090
|
+
return true;
|
|
8091
|
+
}
|
|
8092
|
+
return !isProcessAlive(payload.pid);
|
|
8093
|
+
}
|
|
8094
|
+
function writeLockPayload(lockPath, payload) {
|
|
8095
|
+
const tempPath = `${lockPath}.${payload.token}.tmp`;
|
|
8096
|
+
writeJsonAtomic(tempPath, payload);
|
|
8097
|
+
import_node_fs4.default.renameSync(tempPath, lockPath);
|
|
8098
|
+
}
|
|
8099
|
+
function createLockPayload(workspaceRoot, reason) {
|
|
8100
|
+
return {
|
|
8101
|
+
token: newBuildId(),
|
|
8102
|
+
pid: process.pid,
|
|
8103
|
+
reason,
|
|
8104
|
+
workspaceRoot: import_node_path5.default.resolve(workspaceRoot),
|
|
8105
|
+
acquiredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8106
|
+
};
|
|
8107
|
+
}
|
|
8108
|
+
function withWorkspaceWriteLock(workspaceRoot, reason, callback, options3) {
|
|
8109
|
+
const lockPath = getLockPath(workspaceRoot);
|
|
8110
|
+
const timeoutMs = options3?.timeoutMs ?? LOCK_WAIT_TIMEOUT_MS;
|
|
8111
|
+
const deadline = Date.now() + timeoutMs;
|
|
8112
|
+
const payload = createLockPayload(workspaceRoot, reason);
|
|
8113
|
+
ensureDir(import_node_path5.default.dirname(lockPath));
|
|
8114
|
+
while (true) {
|
|
8115
|
+
try {
|
|
8116
|
+
const fileDescriptor = import_node_fs4.default.openSync(lockPath, "wx");
|
|
8117
|
+
import_node_fs4.default.closeSync(fileDescriptor);
|
|
8118
|
+
writeLockPayload(lockPath, payload);
|
|
8119
|
+
break;
|
|
8120
|
+
} catch (error) {
|
|
8121
|
+
const code = error.code;
|
|
8122
|
+
if (code !== "EEXIST") {
|
|
8123
|
+
throw error;
|
|
8124
|
+
}
|
|
8125
|
+
const existing = readLockPayload(lockPath);
|
|
8126
|
+
if (canBreakLock(existing)) {
|
|
8127
|
+
import_node_fs4.default.rmSync(lockPath, { force: true });
|
|
8128
|
+
continue;
|
|
8129
|
+
}
|
|
8130
|
+
if (Date.now() >= deadline) {
|
|
8131
|
+
throw new CliError(
|
|
8132
|
+
"WORKSPACE_BUSY",
|
|
8133
|
+
"Another write operation is already running for this workspace.",
|
|
8134
|
+
EXIT_CODES.workspaceBusy,
|
|
8135
|
+
{
|
|
8136
|
+
hint: "Parallel reads should continue to work. For writes or auto-rebuilds, wait for the active write to finish and retry.",
|
|
8137
|
+
details: {
|
|
8138
|
+
lockPath,
|
|
8139
|
+
holder: existing
|
|
8140
|
+
}
|
|
8141
|
+
}
|
|
8142
|
+
);
|
|
8143
|
+
}
|
|
8144
|
+
sleepMs(LOCK_POLL_INTERVAL_MS);
|
|
8145
|
+
}
|
|
8146
|
+
}
|
|
8147
|
+
const artificialDelay = Number(process.env.COMPANY_AGENT_WIKI_TEST_WRITE_LOCK_DELAY_MS || "0");
|
|
8148
|
+
if (Number.isFinite(artificialDelay) && artificialDelay > 0) {
|
|
8149
|
+
sleepMs(artificialDelay);
|
|
8150
|
+
}
|
|
8151
|
+
try {
|
|
8152
|
+
return callback();
|
|
8153
|
+
} finally {
|
|
8154
|
+
const current = readLockPayload(lockPath);
|
|
8155
|
+
if (current && current.token === payload.token) {
|
|
8156
|
+
import_node_fs4.default.rmSync(lockPath, { force: true });
|
|
8157
|
+
}
|
|
8158
|
+
}
|
|
8159
|
+
}
|
|
8160
|
+
|
|
7852
8161
|
// src/lib/indexer.ts
|
|
7853
8162
|
function openDatabase(databasePath, options3) {
|
|
7854
8163
|
try {
|
|
@@ -7857,6 +8166,12 @@ function openDatabase(databasePath, options3) {
|
|
|
7857
8166
|
options3?.readonly ? { readonly: true, fileMustExist: true } : void 0
|
|
7858
8167
|
);
|
|
7859
8168
|
database.pragma("busy_timeout = 5000");
|
|
8169
|
+
if (options3?.readonly) {
|
|
8170
|
+
database.pragma("query_only = 1");
|
|
8171
|
+
} else {
|
|
8172
|
+
database.pragma("journal_mode = WAL");
|
|
8173
|
+
database.pragma("synchronous = NORMAL");
|
|
8174
|
+
}
|
|
7860
8175
|
return database;
|
|
7861
8176
|
} catch (error) {
|
|
7862
8177
|
throw coerceCliError(error, {
|
|
@@ -7875,11 +8190,11 @@ function closeDatabaseQuietly(database) {
|
|
|
7875
8190
|
}
|
|
7876
8191
|
function throwKnownDatabaseError(error, workspaceRoot) {
|
|
7877
8192
|
const cliError = coerceCliError(error, {
|
|
7878
|
-
sqliteLockHint: `Retry in a moment, serialize parallel CLI reads against ${
|
|
8193
|
+
sqliteLockHint: `Retry in a moment, serialize parallel CLI reads against ${import_node_path6.default.resolve(
|
|
7879
8194
|
workspaceRoot
|
|
7880
8195
|
)}, or rerun with --auto-rebuild after the current write finishes.`,
|
|
7881
8196
|
sqliteLockDetails: {
|
|
7882
|
-
workspaceRoot:
|
|
8197
|
+
workspaceRoot: import_node_path6.default.resolve(workspaceRoot)
|
|
7883
8198
|
}
|
|
7884
8199
|
});
|
|
7885
8200
|
if (cliError) {
|
|
@@ -7961,8 +8276,8 @@ function collectRootSnapshot(rootId, rootPath, kind) {
|
|
|
7961
8276
|
const entries = [];
|
|
7962
8277
|
let latestMtimeMs = 0;
|
|
7963
8278
|
for (const filePath of markdownFiles) {
|
|
7964
|
-
const stats =
|
|
7965
|
-
const relPath =
|
|
8279
|
+
const stats = import_node_fs5.default.statSync(filePath);
|
|
8280
|
+
const relPath = import_node_path6.default.relative(rootPath, filePath);
|
|
7966
8281
|
latestMtimeMs = Math.max(latestMtimeMs, Math.trunc(stats.mtimeMs));
|
|
7967
8282
|
entries.push(`${relPath}|${stats.size}|${Math.trunc(stats.mtimeMs)}`);
|
|
7968
8283
|
}
|
|
@@ -8150,13 +8465,13 @@ function matchesFilters(metadata, filters) {
|
|
|
8150
8465
|
}
|
|
8151
8466
|
return true;
|
|
8152
8467
|
}
|
|
8153
|
-
function
|
|
8468
|
+
function rebuildIndexUnlocked(workspaceRoot) {
|
|
8154
8469
|
const config = loadWorkspaceConfig(workspaceRoot);
|
|
8155
8470
|
const paths = resolveWorkspacePaths(workspaceRoot);
|
|
8156
|
-
const tempDbPath = `${paths.indexDbPath}.next`;
|
|
8471
|
+
const tempDbPath = `${paths.indexDbPath}.${process.pid}.${Date.now()}.${newBuildId()}.next`;
|
|
8157
8472
|
const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8158
8473
|
if (fileExists(tempDbPath)) {
|
|
8159
|
-
|
|
8474
|
+
import_node_fs5.default.unlinkSync(tempDbPath);
|
|
8160
8475
|
}
|
|
8161
8476
|
let database;
|
|
8162
8477
|
try {
|
|
@@ -8186,9 +8501,9 @@ function rebuildIndex(workspaceRoot) {
|
|
|
8186
8501
|
insertRoot(database, snapshot, indexedAt);
|
|
8187
8502
|
const markdownFiles = walkMarkdownFiles(rootPath);
|
|
8188
8503
|
for (const filePath of markdownFiles) {
|
|
8189
|
-
const rawContent =
|
|
8190
|
-
const stats =
|
|
8191
|
-
const relPath =
|
|
8504
|
+
const rawContent = import_node_fs5.default.readFileSync(filePath, "utf8");
|
|
8505
|
+
const stats = import_node_fs5.default.statSync(filePath);
|
|
8506
|
+
const relPath = import_node_path6.default.relative(rootPath, filePath);
|
|
8192
8507
|
const parsed = parseMarkdownDocument(filePath, relPath, root.id, rawContent, Math.trunc(stats.mtimeMs));
|
|
8193
8508
|
insertDocument(database, parsed.document);
|
|
8194
8509
|
insertSections(database, parsed.document, parsed.sections);
|
|
@@ -8199,8 +8514,8 @@ function rebuildIndex(workspaceRoot) {
|
|
|
8199
8514
|
database.exec("INSERT INTO sections_fts(sections_fts) VALUES('optimize');");
|
|
8200
8515
|
closeDatabaseQuietly(database);
|
|
8201
8516
|
database = void 0;
|
|
8202
|
-
replaceFileAtomic(paths.indexDbPath,
|
|
8203
|
-
|
|
8517
|
+
replaceFileAtomic(paths.indexDbPath, import_node_fs5.default.readFileSync(tempDbPath));
|
|
8518
|
+
import_node_fs5.default.unlinkSync(tempDbPath);
|
|
8204
8519
|
const manifest = {
|
|
8205
8520
|
buildId,
|
|
8206
8521
|
schemaVersion: INDEX_SCHEMA_VERSION,
|
|
@@ -8215,11 +8530,14 @@ function rebuildIndex(workspaceRoot) {
|
|
|
8215
8530
|
} catch (error) {
|
|
8216
8531
|
closeDatabaseQuietly(database);
|
|
8217
8532
|
if (fileExists(tempDbPath)) {
|
|
8218
|
-
|
|
8533
|
+
import_node_fs5.default.rmSync(tempDbPath, { force: true });
|
|
8219
8534
|
}
|
|
8220
8535
|
throwKnownDatabaseError(error, workspaceRoot);
|
|
8221
8536
|
}
|
|
8222
8537
|
}
|
|
8538
|
+
function rebuildIndex(workspaceRoot) {
|
|
8539
|
+
return withWorkspaceWriteLock(workspaceRoot, "index-rebuild", () => rebuildIndexUnlocked(workspaceRoot));
|
|
8540
|
+
}
|
|
8223
8541
|
function readManifest(workspaceRoot) {
|
|
8224
8542
|
const paths = resolveWorkspacePaths(workspaceRoot);
|
|
8225
8543
|
if (!fileExists(paths.indexManifestPath)) {
|
|
@@ -8297,7 +8615,7 @@ function requireFreshIndex(workspaceRoot, options3) {
|
|
|
8297
8615
|
"The workspace has not been indexed yet.",
|
|
8298
8616
|
EXIT_CODES.indexMissing,
|
|
8299
8617
|
{
|
|
8300
|
-
hint: verification.hint || `Run: company-agent-wiki-cli index rebuild --workspace ${
|
|
8618
|
+
hint: verification.hint || `Run: company-agent-wiki-cli index rebuild --workspace ${import_node_path6.default.resolve(workspaceRoot)}`
|
|
8301
8619
|
}
|
|
8302
8620
|
);
|
|
8303
8621
|
}
|
|
@@ -8310,7 +8628,7 @@ function requireFreshIndex(workspaceRoot, options3) {
|
|
|
8310
8628
|
"The indexed snapshot no longer matches the current roots.",
|
|
8311
8629
|
EXIT_CODES.indexStale,
|
|
8312
8630
|
{
|
|
8313
|
-
hint: `Run: company-agent-wiki-cli index rebuild --workspace ${
|
|
8631
|
+
hint: `Run: company-agent-wiki-cli index rebuild --workspace ${import_node_path6.default.resolve(workspaceRoot)}`,
|
|
8314
8632
|
details: verification.roots.filter((root) => !root.ok)
|
|
8315
8633
|
}
|
|
8316
8634
|
);
|
|
@@ -8619,8 +8937,8 @@ function getDocumentHeadings(workspaceRoot, docId, options3) {
|
|
|
8619
8937
|
}
|
|
8620
8938
|
|
|
8621
8939
|
// src/lib/onboarding.ts
|
|
8622
|
-
var
|
|
8623
|
-
var
|
|
8940
|
+
var import_node_fs6 = __toESM(require("node:fs"));
|
|
8941
|
+
var import_node_path7 = __toESM(require("node:path"));
|
|
8624
8942
|
var COMPANY_ONBOARDING_DE_V1 = {
|
|
8625
8943
|
profileId: "de-company-v1",
|
|
8626
8944
|
locale: "de-DE",
|
|
@@ -9212,8 +9530,8 @@ function ensureKnownAnswerKeys(payload) {
|
|
|
9212
9530
|
}
|
|
9213
9531
|
}
|
|
9214
9532
|
function isPathInsideWorkspace2(workspaceRoot, candidatePath) {
|
|
9215
|
-
const relative =
|
|
9216
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
9533
|
+
const relative = import_node_path7.default.relative(import_node_path7.default.resolve(workspaceRoot), import_node_path7.default.resolve(candidatePath));
|
|
9534
|
+
return relative === "" || !relative.startsWith("..") && !import_node_path7.default.isAbsolute(relative);
|
|
9217
9535
|
}
|
|
9218
9536
|
function resolveManagedRoot(workspaceRoot) {
|
|
9219
9537
|
const config = loadWorkspaceConfig(workspaceRoot);
|
|
@@ -9236,12 +9554,12 @@ function resolveManagedRoot(workspaceRoot) {
|
|
|
9236
9554
|
return resolvedPath;
|
|
9237
9555
|
}
|
|
9238
9556
|
function createDocument(workspaceRoot, managedRoot, relPath, id, title, type, tags, body, answeredAt, answeredBy) {
|
|
9239
|
-
const absPath =
|
|
9557
|
+
const absPath = import_node_path7.default.join(managedRoot, relPath);
|
|
9240
9558
|
return {
|
|
9241
9559
|
docId: id,
|
|
9242
9560
|
title,
|
|
9243
9561
|
absPath,
|
|
9244
|
-
relPath:
|
|
9562
|
+
relPath: import_node_path7.default.relative(workspaceRoot, absPath),
|
|
9245
9563
|
existed: false,
|
|
9246
9564
|
content: `${renderFrontmatter({ id, title, type, tags, answeredAt, answeredBy })}${body.trimEnd()}
|
|
9247
9565
|
`
|
|
@@ -9440,7 +9758,7 @@ function buildCompanyDocuments(workspaceRoot, normalized) {
|
|
|
9440
9758
|
function loadCompanyOnboardingAnswers(answerFile) {
|
|
9441
9759
|
const payload = readJsonFile(answerFile);
|
|
9442
9760
|
ensureKnownAnswerKeys(payload);
|
|
9443
|
-
const stats =
|
|
9761
|
+
const stats = import_node_fs6.default.statSync(answerFile);
|
|
9444
9762
|
const normalized = normalizeAnswers(payload, stats.mtime.toISOString());
|
|
9445
9763
|
if (normalized.profileId !== COMPANY_ONBOARDING_DE_V1.profileId) {
|
|
9446
9764
|
throw new CliError(
|
|
@@ -9464,7 +9782,7 @@ function previewCompanyOnboarding(workspaceRoot, answerFile) {
|
|
|
9464
9782
|
);
|
|
9465
9783
|
}
|
|
9466
9784
|
for (const document of materialized.documents) {
|
|
9467
|
-
document.existed =
|
|
9785
|
+
document.existed = import_node_fs6.default.existsSync(document.absPath);
|
|
9468
9786
|
}
|
|
9469
9787
|
return {
|
|
9470
9788
|
documents: materialized.documents,
|
|
@@ -9473,39 +9791,41 @@ function previewCompanyOnboarding(workspaceRoot, answerFile) {
|
|
|
9473
9791
|
};
|
|
9474
9792
|
}
|
|
9475
9793
|
function applyCompanyOnboarding(options3) {
|
|
9476
|
-
const workspaceRoot =
|
|
9477
|
-
const answerFile =
|
|
9794
|
+
const workspaceRoot = import_node_path7.default.resolve(options3.workspaceRoot);
|
|
9795
|
+
const answerFile = import_node_path7.default.resolve(options3.answerFile);
|
|
9478
9796
|
const preview = previewCompanyOnboarding(workspaceRoot, answerFile);
|
|
9479
9797
|
const warnings = [...preview.warnings];
|
|
9480
9798
|
let indexBuildId;
|
|
9481
9799
|
if (options3.execute) {
|
|
9482
|
-
const
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9800
|
+
const manifest = withWorkspaceWriteLock(workspaceRoot, "onboarding-apply", () => {
|
|
9801
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
9802
|
+
for (const document of preview.documents) {
|
|
9803
|
+
if (seenPaths.has(document.absPath)) {
|
|
9804
|
+
throw new CliError(
|
|
9805
|
+
"ONBOARDING_TARGET_CONFLICT",
|
|
9806
|
+
`Multiple onboarding documents resolve to the same target path: ${document.relPath}`,
|
|
9807
|
+
EXIT_CODES.validation
|
|
9808
|
+
);
|
|
9809
|
+
}
|
|
9810
|
+
seenPaths.add(document.absPath);
|
|
9811
|
+
if (document.existed && !options3.force) {
|
|
9812
|
+
throw new CliError(
|
|
9813
|
+
"ONBOARDING_TARGET_EXISTS",
|
|
9814
|
+
`Target file already exists: ${document.relPath}`,
|
|
9815
|
+
EXIT_CODES.validation,
|
|
9816
|
+
{ hint: "Use --force to overwrite generated onboarding files." }
|
|
9817
|
+
);
|
|
9818
|
+
}
|
|
9499
9819
|
}
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9820
|
+
for (const document of preview.documents) {
|
|
9821
|
+
ensureDir(import_node_path7.default.dirname(document.absPath));
|
|
9822
|
+
if (document.existed) {
|
|
9823
|
+
warnings.push(`Overwriting existing file: ${document.relPath}`);
|
|
9824
|
+
}
|
|
9825
|
+
replaceFileAtomic(document.absPath, document.content);
|
|
9505
9826
|
}
|
|
9506
|
-
|
|
9507
|
-
}
|
|
9508
|
-
const manifest = rebuildIndex(workspaceRoot);
|
|
9827
|
+
return rebuildIndexUnlocked(workspaceRoot);
|
|
9828
|
+
});
|
|
9509
9829
|
indexBuildId = manifest.buildId;
|
|
9510
9830
|
}
|
|
9511
9831
|
return {
|
|
@@ -9568,7 +9888,7 @@ function printJson(value) {
|
|
|
9568
9888
|
}
|
|
9569
9889
|
|
|
9570
9890
|
// src/lib/server.ts
|
|
9571
|
-
var
|
|
9891
|
+
var import_node_fs7 = __toESM(require("node:fs"));
|
|
9572
9892
|
var import_node_http = __toESM(require("node:http"));
|
|
9573
9893
|
var import_node_url = require("node:url");
|
|
9574
9894
|
|
|
@@ -12027,6 +12347,7 @@ function getHttpStatusCode(error) {
|
|
|
12027
12347
|
case "INDEX_STALE":
|
|
12028
12348
|
return 409;
|
|
12029
12349
|
case "SQLITE_LOCKED":
|
|
12350
|
+
case "WORKSPACE_BUSY":
|
|
12030
12351
|
return 423;
|
|
12031
12352
|
default:
|
|
12032
12353
|
return 500;
|
|
@@ -12133,7 +12454,7 @@ function startServer(workspaceRoot, port, options3) {
|
|
|
12133
12454
|
return;
|
|
12134
12455
|
}
|
|
12135
12456
|
const resolved = resolveDocumentById(workspaceRoot, docId, { autoRebuild: options3?.autoRebuild });
|
|
12136
|
-
const rawMarkdown =
|
|
12457
|
+
const rawMarkdown = import_node_fs7.default.readFileSync(resolved.absPath, "utf8");
|
|
12137
12458
|
sendJson(response, {
|
|
12138
12459
|
ok: true,
|
|
12139
12460
|
data: {
|
|
@@ -12189,14 +12510,16 @@ function startServer(workspaceRoot, port, options3) {
|
|
|
12189
12510
|
// src/index.ts
|
|
12190
12511
|
function assertWorkspace(workspacePath) {
|
|
12191
12512
|
if (workspacePath?.trim()) {
|
|
12192
|
-
|
|
12513
|
+
const resolved = import_node_path8.default.resolve(workspacePath);
|
|
12514
|
+
rememberWorkspaceGlobally(resolved, { setDefault: true, source: "runtime" });
|
|
12515
|
+
return resolved;
|
|
12193
12516
|
}
|
|
12194
|
-
const
|
|
12195
|
-
if (
|
|
12196
|
-
return
|
|
12517
|
+
const selection = resolveWorkspaceSelection(process.cwd());
|
|
12518
|
+
if (selection.workspaceRoot) {
|
|
12519
|
+
return selection.workspaceRoot;
|
|
12197
12520
|
}
|
|
12198
12521
|
throw new CliError("WORKSPACE_REQUIRED", "Missing --workspace option and no workspace was detected from the current directory.", EXIT_CODES.usage, {
|
|
12199
|
-
hint:
|
|
12522
|
+
hint: `Pass --workspace /absolute/path, run the command from a directory inside the private workspace, or register one globally in ${getGlobalRegistryPath()}.`
|
|
12200
12523
|
});
|
|
12201
12524
|
}
|
|
12202
12525
|
function printHumanChecks(checks) {
|
|
@@ -12281,8 +12604,10 @@ program2.command("about").description("Show CLI runtime metadata and common Code
|
|
|
12281
12604
|
cliName: CLI_NAME,
|
|
12282
12605
|
schemaVersion: CLI_SCHEMA_VERSION,
|
|
12283
12606
|
codexHome,
|
|
12284
|
-
codexShimPath:
|
|
12285
|
-
cwdWorkspace: detectWorkspaceRoot(process.cwd()) || null
|
|
12607
|
+
codexShimPath: import_node_path8.default.join(codexHome, "bin", CLI_NAME),
|
|
12608
|
+
cwdWorkspace: detectWorkspaceRoot(process.cwd()) || null,
|
|
12609
|
+
globalRegistryPath: getGlobalRegistryPath(),
|
|
12610
|
+
resolvedWorkspace: resolveWorkspaceSelection(process.cwd())
|
|
12286
12611
|
};
|
|
12287
12612
|
if (options3.json) {
|
|
12288
12613
|
printJson(envelope("about", data));
|
|
@@ -12298,10 +12623,101 @@ program2.command("about").description("Show CLI runtime metadata and common Code
|
|
|
12298
12623
|
process.stdout.write(` detected workspace: ${data.cwdWorkspace}
|
|
12299
12624
|
`);
|
|
12300
12625
|
}
|
|
12626
|
+
if (data.resolvedWorkspace.workspaceRoot && data.resolvedWorkspace.source !== "cwd") {
|
|
12627
|
+
process.stdout.write(` resolved workspace: ${data.resolvedWorkspace.workspaceRoot} (${data.resolvedWorkspace.source})
|
|
12628
|
+
`);
|
|
12629
|
+
}
|
|
12630
|
+
process.stdout.write(` global registry: ${data.globalRegistryPath}
|
|
12631
|
+
`);
|
|
12632
|
+
});
|
|
12633
|
+
var workspace = new Command("workspace").description("Manage global workspace discovery");
|
|
12634
|
+
workspace.command("current").description("Show the currently resolved workspace and discovery source").option("--json", "Emit JSON output", false).action((options3) => {
|
|
12635
|
+
const selection = resolveWorkspaceSelection(process.cwd());
|
|
12636
|
+
const data = {
|
|
12637
|
+
workspaceRoot: selection.workspaceRoot || null,
|
|
12638
|
+
source: selection.source || null,
|
|
12639
|
+
registryPath: selection.registryPath,
|
|
12640
|
+
defaultWorkspace: selection.defaultWorkspace || null
|
|
12641
|
+
};
|
|
12642
|
+
if (options3.json) {
|
|
12643
|
+
printJson(envelope("workspace current", data));
|
|
12644
|
+
return;
|
|
12645
|
+
}
|
|
12646
|
+
if (data.workspaceRoot) {
|
|
12647
|
+
process.stdout.write(`Resolved workspace: ${data.workspaceRoot}
|
|
12648
|
+
`);
|
|
12649
|
+
process.stdout.write(`Source: ${data.source}
|
|
12650
|
+
`);
|
|
12651
|
+
} else {
|
|
12652
|
+
process.stdout.write("No workspace resolved.\n");
|
|
12653
|
+
}
|
|
12654
|
+
process.stdout.write(`Global registry: ${data.registryPath}
|
|
12655
|
+
`);
|
|
12656
|
+
if (data.defaultWorkspace) {
|
|
12657
|
+
process.stdout.write(`Default workspace: ${data.defaultWorkspace}
|
|
12658
|
+
`);
|
|
12659
|
+
}
|
|
12660
|
+
});
|
|
12661
|
+
workspace.command("list").description("List globally registered workspaces").option("--json", "Emit JSON output", false).action((options3) => {
|
|
12662
|
+
const result = listRegisteredWorkspaces();
|
|
12663
|
+
if (options3.json) {
|
|
12664
|
+
printJson(envelope("workspace list", result));
|
|
12665
|
+
return;
|
|
12666
|
+
}
|
|
12667
|
+
process.stdout.write(`Global registry: ${result.registryPath}
|
|
12668
|
+
`);
|
|
12669
|
+
if (result.workspaces.length === 0) {
|
|
12670
|
+
process.stdout.write("No registered workspaces.\n");
|
|
12671
|
+
return;
|
|
12672
|
+
}
|
|
12673
|
+
for (const item of result.workspaces) {
|
|
12674
|
+
const defaultMarker = result.defaultWorkspace === item.path ? " [default]" : "";
|
|
12675
|
+
const existsMarker = item.exists ? "" : " [missing]";
|
|
12676
|
+
process.stdout.write(`- ${item.label}${defaultMarker}${existsMarker}
|
|
12677
|
+
`);
|
|
12678
|
+
process.stdout.write(` ${item.path}
|
|
12679
|
+
`);
|
|
12680
|
+
}
|
|
12681
|
+
});
|
|
12682
|
+
workspace.command("register").description("Register an existing workspace globally for other agents").requiredOption("--workspace <path>", "Absolute or relative workspace path").option("--default", "Also mark this workspace as the global default", false).option("--json", "Emit JSON output", false).action((options3) => {
|
|
12683
|
+
const entry = registerWorkspaceGlobally(import_node_path8.default.resolve(options3.workspace), {
|
|
12684
|
+
setDefault: Boolean(options3.default),
|
|
12685
|
+
source: "manual"
|
|
12686
|
+
});
|
|
12687
|
+
const result = {
|
|
12688
|
+
registryPath: getGlobalRegistryPath(),
|
|
12689
|
+
entry
|
|
12690
|
+
};
|
|
12691
|
+
if (options3.json) {
|
|
12692
|
+
printJson(envelope("workspace register", result));
|
|
12693
|
+
return;
|
|
12694
|
+
}
|
|
12695
|
+
process.stdout.write(`Registered workspace: ${entry.path}
|
|
12696
|
+
`);
|
|
12697
|
+
if (options3.default) {
|
|
12698
|
+
process.stdout.write("This workspace is now the global default.\n");
|
|
12699
|
+
}
|
|
12700
|
+
});
|
|
12701
|
+
workspace.command("use").description("Set a registered workspace as the global default").requiredOption("--workspace <path>", "Absolute or relative workspace path").option("--json", "Emit JSON output", false).action((options3) => {
|
|
12702
|
+
const entry = registerWorkspaceGlobally(import_node_path8.default.resolve(options3.workspace), {
|
|
12703
|
+
setDefault: true,
|
|
12704
|
+
source: "manual"
|
|
12705
|
+
});
|
|
12706
|
+
const result = {
|
|
12707
|
+
registryPath: getGlobalRegistryPath(),
|
|
12708
|
+
defaultWorkspace: entry.path
|
|
12709
|
+
};
|
|
12710
|
+
if (options3.json) {
|
|
12711
|
+
printJson(envelope("workspace use", result));
|
|
12712
|
+
return;
|
|
12713
|
+
}
|
|
12714
|
+
process.stdout.write(`Global default workspace: ${entry.path}
|
|
12715
|
+
`);
|
|
12301
12716
|
});
|
|
12717
|
+
program2.addCommand(workspace);
|
|
12302
12718
|
program2.command("setup").description("Workspace setup commands").addCommand(
|
|
12303
12719
|
new Command("workspace").requiredOption("--workspace <path>", "Absolute or relative workspace path").option("--git-init", "Initialize a local Git repository", false).option("--git-remote <url>", "Configure a Git remote URL").option("--no-starter-docs", "Skip creation of starter Markdown documents").option("--force", "Rewrite an existing scaffold", false).option("--json", "Emit JSON output", false).action((options3) => {
|
|
12304
|
-
const workspaceRoot =
|
|
12720
|
+
const workspaceRoot = import_node_path8.default.resolve(options3.workspace);
|
|
12305
12721
|
const result = setupWorkspace({
|
|
12306
12722
|
workspaceRoot,
|
|
12307
12723
|
gitInit: Boolean(options3.gitInit),
|
|
@@ -12555,8 +12971,8 @@ program2.command("read").option("--workspace <path>", "Workspace path. Optional
|
|
|
12555
12971
|
const metadataResult = options3.docId ? getDocumentMetadataById(workspaceRoot, options3.docId, {
|
|
12556
12972
|
autoRebuild: Boolean(options3.autoRebuild)
|
|
12557
12973
|
}) : (() => {
|
|
12558
|
-
const candidatePath =
|
|
12559
|
-
return getDocumentMetadataByPath(workspaceRoot,
|
|
12974
|
+
const candidatePath = import_node_path8.default.isAbsolute(options3.path) ? options3.path : import_node_path8.default.join(workspaceRoot, options3.path);
|
|
12975
|
+
return getDocumentMetadataByPath(workspaceRoot, import_node_path8.default.resolve(candidatePath), {
|
|
12560
12976
|
autoRebuild: Boolean(options3.autoRebuild)
|
|
12561
12977
|
});
|
|
12562
12978
|
})();
|
|
@@ -12584,7 +13000,7 @@ program2.command("read").option("--workspace <path>", "Workspace path. Optional
|
|
|
12584
13000
|
}
|
|
12585
13001
|
return;
|
|
12586
13002
|
}
|
|
12587
|
-
const rawMarkdown =
|
|
13003
|
+
const rawMarkdown = import_node_fs8.default.readFileSync(metadataResult.metadata.absPath, "utf8");
|
|
12588
13004
|
if (options3.json) {
|
|
12589
13005
|
printJson(
|
|
12590
13006
|
envelope(
|
|
@@ -12606,7 +13022,7 @@ program2.command("read").option("--workspace <path>", "Workspace path. Optional
|
|
|
12606
13022
|
});
|
|
12607
13023
|
program2.command("history").option("--workspace <path>", "Workspace path. Optional when current directory is already inside a workspace.").option("--doc-id <id>", "Indexed document identifier").option("--path <path>", "Absolute or workspace-relative document path").option("--limit <number>", "Maximum number of commits", "20").option("--json", "Emit JSON output", false).action((options3) => {
|
|
12608
13024
|
const workspaceRoot = assertWorkspace(options3.workspace);
|
|
12609
|
-
const resolvedPath = options3.docId ? resolveDocumentById(workspaceRoot, options3.docId).absPath :
|
|
13025
|
+
const resolvedPath = options3.docId ? resolveDocumentById(workspaceRoot, options3.docId).absPath : import_node_path8.default.resolve(import_node_path8.default.isAbsolute(options3.path) ? options3.path : import_node_path8.default.join(workspaceRoot, options3.path));
|
|
12610
13026
|
const history = getGitHistory(resolvedPath, Number(options3.limit));
|
|
12611
13027
|
if (options3.json) {
|
|
12612
13028
|
printJson(envelope("history", { path: resolvedPath, history }));
|
|
@@ -12619,7 +13035,7 @@ program2.command("history").option("--workspace <path>", "Workspace path. Option
|
|
|
12619
13035
|
});
|
|
12620
13036
|
program2.command("diff").option("--workspace <path>", "Workspace path. Optional when current directory is already inside a workspace.").option("--doc-id <id>", "Indexed document identifier").option("--path <path>", "Absolute or workspace-relative document path").option("--base <ref>", "Base Git ref", "HEAD").option("--compare <ref>", "Optional compare ref").option("--json", "Emit JSON output", false).action((options3) => {
|
|
12621
13037
|
const workspaceRoot = assertWorkspace(options3.workspace);
|
|
12622
|
-
const resolvedPath = options3.docId ? resolveDocumentById(workspaceRoot, options3.docId).absPath :
|
|
13038
|
+
const resolvedPath = options3.docId ? resolveDocumentById(workspaceRoot, options3.docId).absPath : import_node_path8.default.resolve(import_node_path8.default.isAbsolute(options3.path) ? options3.path : import_node_path8.default.join(workspaceRoot, options3.path));
|
|
12623
13039
|
const diff = getGitDiff(resolvedPath, options3.base, options3.compare);
|
|
12624
13040
|
if (options3.json) {
|
|
12625
13041
|
printJson(envelope("diff", { path: resolvedPath, diff }));
|