agendex-cli 1.1.0 → 1.2.0
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 +3 -0
- package/dist/cli.js +188 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,9 @@ agendex configure # Select which agents/adapters to index
|
|
|
23
23
|
agendex start # Start daemon (backgrounds itself)
|
|
24
24
|
agendex stop # Stop the running daemon
|
|
25
25
|
agendex sync # One-shot scan + sync to cloud
|
|
26
|
+
agendex upload <path> # Upload a single Markdown plan file to the cloud
|
|
27
|
+
agendex upload <path> --agent <name> # Override the uploaded plan's agent label
|
|
28
|
+
agendex upload <path> --open # Open the uploaded plan in the browser after upload
|
|
26
29
|
agendex cleanup # Interactively remove cloud daemons
|
|
27
30
|
agendex cleanup --stale # Auto-remove all stale daemons
|
|
28
31
|
agendex status # Show config state, daemon status, uptime & hostname
|
package/dist/cli.js
CHANGED
|
@@ -1059,8 +1059,8 @@ var init_cleanup = __esm(() => {
|
|
|
1059
1059
|
|
|
1060
1060
|
// src/cli.ts
|
|
1061
1061
|
import { spawn as spawn4 } from "node:child_process";
|
|
1062
|
-
import { existsSync as
|
|
1063
|
-
import { resolve as
|
|
1062
|
+
import { existsSync as existsSync13, statSync as statSync2, writeSync } from "node:fs";
|
|
1063
|
+
import { resolve as resolve10 } from "node:path";
|
|
1064
1064
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1065
1065
|
|
|
1066
1066
|
// ../shared/src/adapters/catalog.ts
|
|
@@ -2822,6 +2822,7 @@ function normalizeStoredConfig(raw) {
|
|
|
2822
2822
|
const token = typeof raw.token === "string" && raw.token.trim() ? raw.token : undefined;
|
|
2823
2823
|
const cloudToken = typeof raw.cloudToken === "string" && raw.cloudToken.trim() ? raw.cloudToken : undefined;
|
|
2824
2824
|
const convexUrl = typeof raw.convexUrl === "string" && raw.convexUrl.trim() ? raw.convexUrl : undefined;
|
|
2825
|
+
const siteUrl = typeof raw.siteUrl === "string" && raw.siteUrl.trim() ? raw.siteUrl : undefined;
|
|
2825
2826
|
const deviceId = typeof raw.deviceId === "string" && raw.deviceId.trim() ? raw.deviceId : undefined;
|
|
2826
2827
|
const collectLocalIpAddress = typeof raw.collectLocalIpAddress === "boolean" ? raw.collectLocalIpAddress : undefined;
|
|
2827
2828
|
return {
|
|
@@ -2829,6 +2830,7 @@ function normalizeStoredConfig(raw) {
|
|
|
2829
2830
|
token,
|
|
2830
2831
|
cloudToken,
|
|
2831
2832
|
convexUrl,
|
|
2833
|
+
siteUrl,
|
|
2832
2834
|
deviceId,
|
|
2833
2835
|
collectLocalIpAddress,
|
|
2834
2836
|
enabledAdapters: normalizeAdapterIds(raw.enabledAdapters),
|
|
@@ -2845,6 +2847,7 @@ function saveConfig(config) {
|
|
|
2845
2847
|
token: config.token,
|
|
2846
2848
|
cloudToken: config.cloudToken,
|
|
2847
2849
|
convexUrl: config.convexUrl,
|
|
2850
|
+
siteUrl: config.siteUrl,
|
|
2848
2851
|
deviceId: config.deviceId,
|
|
2849
2852
|
collectLocalIpAddress: config.collectLocalIpAddress,
|
|
2850
2853
|
enabledAdapters: sanitizeEnabledAdapterIds(config.enabledAdapters),
|
|
@@ -2923,6 +2926,7 @@ async function loadOrInitConfig(options = {}) {
|
|
|
2923
2926
|
token: tokenFromEnv ? existing?.token : currentToken,
|
|
2924
2927
|
cloudToken: existing?.cloudToken,
|
|
2925
2928
|
convexUrl: existing?.convexUrl,
|
|
2929
|
+
siteUrl: existing?.siteUrl,
|
|
2926
2930
|
deviceId,
|
|
2927
2931
|
enabledAdapters,
|
|
2928
2932
|
customPlanDirs: existing?.customPlanDirs ?? []
|
|
@@ -3870,7 +3874,8 @@ function parseSyncSuccess(body) {
|
|
|
3870
3874
|
return {
|
|
3871
3875
|
ok: true,
|
|
3872
3876
|
skippedLowValue: result.skippedLowValue === true,
|
|
3873
|
-
deleted: result.deleted === true
|
|
3877
|
+
deleted: result.deleted === true,
|
|
3878
|
+
...typeof result.planId === "string" && { planId: result.planId }
|
|
3874
3879
|
};
|
|
3875
3880
|
} catch {
|
|
3876
3881
|
return { ok: true };
|
|
@@ -3905,7 +3910,7 @@ async function syncPlan(plan) {
|
|
|
3905
3910
|
}
|
|
3906
3911
|
}
|
|
3907
3912
|
if (res.status < 200 || res.status >= 300) {
|
|
3908
|
-
return { ok: false, error: `${res.status}: ${res.body}` };
|
|
3913
|
+
return { ok: false, status: res.status, error: `${res.status}: ${res.body}` };
|
|
3909
3914
|
}
|
|
3910
3915
|
return parseSyncSuccess(res.body);
|
|
3911
3916
|
}
|
|
@@ -4191,6 +4196,12 @@ function getDefaultSiteUrl() {
|
|
|
4191
4196
|
return process.env.AGENDEX_SITE_URL;
|
|
4192
4197
|
return isDevMode() ? DEV_SITE_URL : PROD_SITE_URL;
|
|
4193
4198
|
}
|
|
4199
|
+
function getSiteUrl() {
|
|
4200
|
+
const config = loadConfig();
|
|
4201
|
+
if (config?.siteUrl)
|
|
4202
|
+
return config.siteUrl;
|
|
4203
|
+
return getDefaultSiteUrl();
|
|
4204
|
+
}
|
|
4194
4205
|
function launchBrowser(url, label) {
|
|
4195
4206
|
console.log(`[agendex] Opening ${label}...`);
|
|
4196
4207
|
console.log(`[agendex] If it doesn't open, visit: ${url}`);
|
|
@@ -4203,15 +4214,16 @@ function launchBrowser(url, label) {
|
|
|
4203
4214
|
async function login(siteUrlOverride) {
|
|
4204
4215
|
const { port, result } = await startCallbackServer();
|
|
4205
4216
|
const callbackUrl = `http://127.0.0.1:${port}/callback`;
|
|
4206
|
-
const
|
|
4217
|
+
const existing = loadConfig();
|
|
4218
|
+
const siteUrl = siteUrlOverride ?? existing?.siteUrl ?? getDefaultSiteUrl();
|
|
4207
4219
|
const authUrl = `${siteUrl}/auth/cli?callback=${encodeURIComponent(callbackUrl)}`;
|
|
4208
4220
|
launchBrowser(authUrl, "browser for authentication");
|
|
4209
4221
|
const callback = await result;
|
|
4210
|
-
const existing = loadConfig();
|
|
4211
4222
|
const config = {
|
|
4212
4223
|
configVersion: 3,
|
|
4213
4224
|
cloudToken: callback.token,
|
|
4214
4225
|
convexUrl: callback.convexUrl,
|
|
4226
|
+
siteUrl,
|
|
4215
4227
|
enabledAdapters: existing?.enabledAdapters ?? [],
|
|
4216
4228
|
customPlanDirs: existing?.customPlanDirs ?? [],
|
|
4217
4229
|
...existing?.token ? { token: existing.token } : {},
|
|
@@ -4232,7 +4244,8 @@ function logout() {
|
|
|
4232
4244
|
enabledAdapters: existing.enabledAdapters,
|
|
4233
4245
|
customPlanDirs: existing.customPlanDirs,
|
|
4234
4246
|
...existing.token ? { token: existing.token } : {},
|
|
4235
|
-
...existing.deviceId ? { deviceId: existing.deviceId } : {}
|
|
4247
|
+
...existing.deviceId ? { deviceId: existing.deviceId } : {},
|
|
4248
|
+
...existing.siteUrl ? { siteUrl: existing.siteUrl } : {}
|
|
4236
4249
|
};
|
|
4237
4250
|
saveConfig(config);
|
|
4238
4251
|
console.log("[agendex] Logged out. Cloud token removed.");
|
|
@@ -4376,7 +4389,7 @@ function spawnBrowser(command, args, options = {}) {
|
|
|
4376
4389
|
// src/daemon.ts
|
|
4377
4390
|
import { spawn as spawn2 } from "node:child_process";
|
|
4378
4391
|
import { hostname as osHostname2 } from "node:os";
|
|
4379
|
-
import { resolve as
|
|
4392
|
+
import { resolve as resolve7 } from "node:path";
|
|
4380
4393
|
import { fileURLToPath } from "node:url";
|
|
4381
4394
|
|
|
4382
4395
|
// src/adapters.ts
|
|
@@ -4521,6 +4534,7 @@ function isIpv4Address(address) {
|
|
|
4521
4534
|
}
|
|
4522
4535
|
|
|
4523
4536
|
// src/payload.ts
|
|
4537
|
+
import { basename as basename6, resolve as resolve6 } from "node:path";
|
|
4524
4538
|
var SYNC_METADATA_KEY = "agendexSync";
|
|
4525
4539
|
function isRecord4(value) {
|
|
4526
4540
|
return typeof value === "object" && value !== null;
|
|
@@ -4539,6 +4553,36 @@ function withSyncDeviceMetadata(metadata, deviceId, hostname2, ipAddress) {
|
|
|
4539
4553
|
}
|
|
4540
4554
|
};
|
|
4541
4555
|
}
|
|
4556
|
+
function parseUploadFile(filePath, content, agentOverride) {
|
|
4557
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
|
|
4558
|
+
const override = agentOverride?.trim();
|
|
4559
|
+
let agent = override || "uploaded";
|
|
4560
|
+
if (!override && fmMatch) {
|
|
4561
|
+
const agentLine = fmMatch[1]?.match(/^agent:\s*(.+)$/m);
|
|
4562
|
+
if (agentLine?.[1])
|
|
4563
|
+
agent = agentLine[1].trim();
|
|
4564
|
+
}
|
|
4565
|
+
const body = fmMatch ? content.slice(fmMatch[0].length) : content;
|
|
4566
|
+
const titleMatch = body.match(/^#\s+(.+)/m);
|
|
4567
|
+
const title = titleMatch?.[1]?.trim() || basename6(filePath).replace(/\.md$/i, "") || "Untitled";
|
|
4568
|
+
return { title, agent, body };
|
|
4569
|
+
}
|
|
4570
|
+
function fileToSyncPayload(filePath, content, options = {}) {
|
|
4571
|
+
const absolutePath = resolve6(filePath);
|
|
4572
|
+
const { title, agent, body } = parseUploadFile(absolutePath, content, options.agentOverride);
|
|
4573
|
+
const now = Date.now();
|
|
4574
|
+
return {
|
|
4575
|
+
localPlanId: hashPath(absolutePath),
|
|
4576
|
+
agent,
|
|
4577
|
+
title,
|
|
4578
|
+
content: body,
|
|
4579
|
+
format: "md",
|
|
4580
|
+
filePath: absolutePath,
|
|
4581
|
+
metadata: withSyncDeviceMetadata({ uploaded: true, userCreated: true }, options.deviceId, options.hostname, options.ipAddress),
|
|
4582
|
+
createdAt: options.createdAt ?? now,
|
|
4583
|
+
updatedAt: options.updatedAt ?? now
|
|
4584
|
+
};
|
|
4585
|
+
}
|
|
4542
4586
|
function planToSyncPayload(plan, deviceId, hostname2, ipAddress) {
|
|
4543
4587
|
return {
|
|
4544
4588
|
localPlanId: plan.id,
|
|
@@ -4981,7 +5025,7 @@ async function startSupervisor() {
|
|
|
4981
5025
|
};
|
|
4982
5026
|
process.on("SIGTERM", shutdown);
|
|
4983
5027
|
process.on("SIGINT", shutdown);
|
|
4984
|
-
const scriptPath =
|
|
5028
|
+
const scriptPath = resolve7(process.argv[1] ?? fileURLToPath(new URL("./cli.ts", import.meta.url)));
|
|
4985
5029
|
const restartTimes = [];
|
|
4986
5030
|
while (!stopping) {
|
|
4987
5031
|
const workerArgs = [scriptPath, "start", "--worker"];
|
|
@@ -4991,11 +5035,11 @@ async function startSupervisor() {
|
|
|
4991
5035
|
stdio: ["ignore", "inherit", "inherit"],
|
|
4992
5036
|
env: { ...process.env, ...isDevMode() ? { AGENDEX_DEV: "1" } : {} }
|
|
4993
5037
|
});
|
|
4994
|
-
const exitCode = await new Promise((
|
|
4995
|
-
workerProc?.once("exit", (code) =>
|
|
5038
|
+
const exitCode = await new Promise((resolve8) => {
|
|
5039
|
+
workerProc?.once("exit", (code) => resolve8(code));
|
|
4996
5040
|
workerProc?.once("error", (error) => {
|
|
4997
5041
|
console.error("[agendex] failed to spawn worker:", error);
|
|
4998
|
-
|
|
5042
|
+
resolve8(1);
|
|
4999
5043
|
});
|
|
5000
5044
|
});
|
|
5001
5045
|
workerProc = null;
|
|
@@ -5021,7 +5065,7 @@ async function startSupervisor() {
|
|
|
5021
5065
|
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
|
|
5022
5066
|
import { mkdir as mkdir2, rm, writeFile as writeFile4 } from "node:fs/promises";
|
|
5023
5067
|
import { homedir as homedir10 } from "node:os";
|
|
5024
|
-
import { dirname as dirname4, join as join14, resolve as
|
|
5068
|
+
import { dirname as dirname4, join as join14, resolve as resolve8 } from "node:path";
|
|
5025
5069
|
var SUPPORTED_AGENTS = ["claude-code", "codex", "pi"];
|
|
5026
5070
|
var MANAGED_MARKER = "agendex-plan-review";
|
|
5027
5071
|
var HOOK_TIMEOUT_SECONDS = 345600;
|
|
@@ -5033,7 +5077,7 @@ function commandFor(cliEntry, agent) {
|
|
|
5033
5077
|
return `${shellQuote(process.execPath)} ${shellQuote(cliEntry)} review-plan --hook --agent ${agent}`;
|
|
5034
5078
|
}
|
|
5035
5079
|
function scopeRoot(scope) {
|
|
5036
|
-
return scope === "repo" ?
|
|
5080
|
+
return scope === "repo" ? resolve8(process.env.PWD || process.cwd()) : homedir10();
|
|
5037
5081
|
}
|
|
5038
5082
|
function hooksJsonPath(agent, scope) {
|
|
5039
5083
|
const root = scopeRoot(scope);
|
|
@@ -5358,7 +5402,7 @@ async function runHooksCommand(args, cliEntry) {
|
|
|
5358
5402
|
for (const agent of agents) {
|
|
5359
5403
|
if (agent === "claude-code")
|
|
5360
5404
|
printClaudePreviewWarning(dryRun);
|
|
5361
|
-
const path = await installAgent(agent, scope,
|
|
5405
|
+
const path = await installAgent(agent, scope, resolve8(cliEntry), dryRun);
|
|
5362
5406
|
console.log(`[agendex] ${dryRun ? "would install" : "installed"} ${agent} hook: ${path}`);
|
|
5363
5407
|
}
|
|
5364
5408
|
return 0;
|
|
@@ -5448,7 +5492,7 @@ async function syncAll(force = false) {
|
|
|
5448
5492
|
// src/upgrade.ts
|
|
5449
5493
|
import { spawn as spawn3, spawnSync } from "node:child_process";
|
|
5450
5494
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
5451
|
-
import { dirname as dirname5, resolve as
|
|
5495
|
+
import { dirname as dirname5, resolve as resolve9, sep as sep4 } from "node:path";
|
|
5452
5496
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5453
5497
|
|
|
5454
5498
|
// src/version.ts
|
|
@@ -5458,7 +5502,7 @@ import { join as join15 } from "node:path";
|
|
|
5458
5502
|
// package.json
|
|
5459
5503
|
var package_default = {
|
|
5460
5504
|
name: "agendex-cli",
|
|
5461
|
-
version: "1.
|
|
5505
|
+
version: "1.2.0",
|
|
5462
5506
|
description: "Agendex CLI for login, sync, and daemon workflows",
|
|
5463
5507
|
homepage: "https://github.com/Tyru5/Agendex#readme",
|
|
5464
5508
|
bugs: {
|
|
@@ -5581,9 +5625,9 @@ var PACKAGE_NAME = "agendex-cli";
|
|
|
5581
5625
|
var moduleDir = dirname5(fileURLToPath2(import.meta.url));
|
|
5582
5626
|
function getPackageRoot() {
|
|
5583
5627
|
try {
|
|
5584
|
-
return realpathSync2(
|
|
5628
|
+
return realpathSync2(resolve9(moduleDir, ".."));
|
|
5585
5629
|
} catch {
|
|
5586
|
-
return
|
|
5630
|
+
return resolve9(moduleDir, "..");
|
|
5587
5631
|
}
|
|
5588
5632
|
}
|
|
5589
5633
|
function detectPackageManager(packageRoot) {
|
|
@@ -5765,9 +5809,120 @@ async function runUpgrade(opts) {
|
|
|
5765
5809
|
});
|
|
5766
5810
|
}
|
|
5767
5811
|
|
|
5812
|
+
// src/upload.ts
|
|
5813
|
+
import { readFile as readFile8, stat as stat8 } from "node:fs/promises";
|
|
5814
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
5815
|
+
import { hostname as osHostname4 } from "node:os";
|
|
5816
|
+
function resolveAgentOverride(args) {
|
|
5817
|
+
const idx = args.indexOf("--agent");
|
|
5818
|
+
if (idx === -1)
|
|
5819
|
+
return;
|
|
5820
|
+
const value = args[idx + 1];
|
|
5821
|
+
if (value === undefined || value.startsWith("--"))
|
|
5822
|
+
return "missing";
|
|
5823
|
+
return value;
|
|
5824
|
+
}
|
|
5825
|
+
function resolvePathArg(args) {
|
|
5826
|
+
for (let i = 0;i < args.length; i++) {
|
|
5827
|
+
const a = args[i];
|
|
5828
|
+
if (a === undefined)
|
|
5829
|
+
continue;
|
|
5830
|
+
if (a === "upload" || a === "--dev" || a === "--open")
|
|
5831
|
+
continue;
|
|
5832
|
+
if (a === "--agent") {
|
|
5833
|
+
i++;
|
|
5834
|
+
continue;
|
|
5835
|
+
}
|
|
5836
|
+
if (a.startsWith("--"))
|
|
5837
|
+
continue;
|
|
5838
|
+
return a;
|
|
5839
|
+
}
|
|
5840
|
+
return;
|
|
5841
|
+
}
|
|
5842
|
+
async function runUpload(args, deps) {
|
|
5843
|
+
const syncPlanFn = deps?.syncPlan ?? syncPlan;
|
|
5844
|
+
const log = deps?.log ?? ((m) => console.log(m));
|
|
5845
|
+
const error = deps?.error ?? ((m) => console.error(m));
|
|
5846
|
+
const openBrowser2 = deps?.openBrowser ?? launchBrowser;
|
|
5847
|
+
const pathArg = resolvePathArg(args);
|
|
5848
|
+
if (!pathArg || !pathArg.trim()) {
|
|
5849
|
+
error("[agendex] usage: agendex upload <path> [--agent <name>] [--open]");
|
|
5850
|
+
return 1;
|
|
5851
|
+
}
|
|
5852
|
+
const absolutePath = resolveCustomPlanDirPath(pathArg);
|
|
5853
|
+
if (!existsSync12(absolutePath)) {
|
|
5854
|
+
error(`[agendex] path does not exist: ${absolutePath}`);
|
|
5855
|
+
return 1;
|
|
5856
|
+
}
|
|
5857
|
+
let stats;
|
|
5858
|
+
try {
|
|
5859
|
+
stats = await stat8(absolutePath);
|
|
5860
|
+
} catch (err) {
|
|
5861
|
+
error(`[agendex] could not read path: ${err instanceof Error ? err.message : String(err)}`);
|
|
5862
|
+
return 1;
|
|
5863
|
+
}
|
|
5864
|
+
if (stats.isDirectory()) {
|
|
5865
|
+
error(`[agendex] path is a directory, expected a single file: ${absolutePath}`);
|
|
5866
|
+
return 1;
|
|
5867
|
+
}
|
|
5868
|
+
if (!/\.md$/i.test(absolutePath)) {
|
|
5869
|
+
error(`[agendex] only Markdown (.md) files are supported: ${absolutePath}`);
|
|
5870
|
+
return 1;
|
|
5871
|
+
}
|
|
5872
|
+
const config = loadConfig();
|
|
5873
|
+
if (!config?.cloudToken || !config?.convexUrl) {
|
|
5874
|
+
error("[agendex] not logged in. Run `agendex login` first.");
|
|
5875
|
+
return 1;
|
|
5876
|
+
}
|
|
5877
|
+
let content;
|
|
5878
|
+
try {
|
|
5879
|
+
content = await readFile8(absolutePath, "utf-8");
|
|
5880
|
+
} catch (err) {
|
|
5881
|
+
error(`[agendex] could not read file: ${err instanceof Error ? err.message : String(err)}`);
|
|
5882
|
+
return 1;
|
|
5883
|
+
}
|
|
5884
|
+
const agentOverride = resolveAgentOverride(args);
|
|
5885
|
+
if (agentOverride === "missing") {
|
|
5886
|
+
error("[agendex] usage: agendex upload <path> [--agent <name>] [--open]");
|
|
5887
|
+
error("[agendex] --agent requires a name");
|
|
5888
|
+
return 1;
|
|
5889
|
+
}
|
|
5890
|
+
const ipAddress = await shouldIncludeLocalIpAddressInSync() ? getLocalIpAddress() : undefined;
|
|
5891
|
+
const payload = fileToSyncPayload(absolutePath, content, {
|
|
5892
|
+
agentOverride,
|
|
5893
|
+
deviceId: config.deviceId ?? loadOrCreateDeviceId(),
|
|
5894
|
+
hostname: osHostname4(),
|
|
5895
|
+
ipAddress,
|
|
5896
|
+
createdAt: stats.birthtime.getTime(),
|
|
5897
|
+
updatedAt: stats.mtime.getTime()
|
|
5898
|
+
});
|
|
5899
|
+
const result = await syncPlanFn(payload);
|
|
5900
|
+
if (!result.ok) {
|
|
5901
|
+
if (result.status === 403) {
|
|
5902
|
+
error(`[agendex] ${result.error ?? "Cloud Pro subscription required"}`);
|
|
5903
|
+
error(`[agendex] View plans and pricing: ${getSiteUrl().replace(/\/$/, "")}/#pricing`);
|
|
5904
|
+
return 1;
|
|
5905
|
+
}
|
|
5906
|
+
error(`[agendex] upload failed: ${result.error ?? "unknown error"}`);
|
|
5907
|
+
return 1;
|
|
5908
|
+
}
|
|
5909
|
+
if (result.skippedLowValue) {
|
|
5910
|
+
log(`[agendex] "${payload.title}" was skipped as a low-value plan and was not stored in the cloud.`);
|
|
5911
|
+
return 0;
|
|
5912
|
+
}
|
|
5913
|
+
const site = getSiteUrl().replace(/\/$/, "");
|
|
5914
|
+
const planUrl = result.planId ? `${site}/dashboard?plan=${encodeURIComponent(result.planId)}` : `${site}/dashboard`;
|
|
5915
|
+
log(`[agendex] uploaded "${payload.title}"`);
|
|
5916
|
+
log(`[agendex] ${planUrl}`);
|
|
5917
|
+
if (args.includes("--open")) {
|
|
5918
|
+
openBrowser2(planUrl, "uploaded plan in your browser");
|
|
5919
|
+
}
|
|
5920
|
+
return 0;
|
|
5921
|
+
}
|
|
5922
|
+
|
|
5768
5923
|
// src/web.ts
|
|
5769
5924
|
async function openAgendexWeb(siteUrlOverride) {
|
|
5770
|
-
const base = siteUrlOverride ??
|
|
5925
|
+
const base = siteUrlOverride ?? getSiteUrl();
|
|
5771
5926
|
const url = base.replace(/\/$/, "");
|
|
5772
5927
|
launchBrowser(url, "Agendex in your browser");
|
|
5773
5928
|
}
|
|
@@ -5802,7 +5957,7 @@ function firstCommandToken(argv) {
|
|
|
5802
5957
|
return;
|
|
5803
5958
|
}
|
|
5804
5959
|
var command = firstCommandToken(args) ?? "start";
|
|
5805
|
-
var cliEntry =
|
|
5960
|
+
var cliEntry = resolve10(process.argv[1] ?? fileURLToPath3(import.meta.url));
|
|
5806
5961
|
async function main() {
|
|
5807
5962
|
const isInternal = args.includes("--daemon") || args.includes("--worker");
|
|
5808
5963
|
if (command === "--version" || command === "-v") {
|
|
@@ -5822,6 +5977,7 @@ async function main() {
|
|
|
5822
5977
|
"add-dir",
|
|
5823
5978
|
"remove-dir",
|
|
5824
5979
|
"list-dirs",
|
|
5980
|
+
"upload",
|
|
5825
5981
|
"upgrade",
|
|
5826
5982
|
"help",
|
|
5827
5983
|
"--help",
|
|
@@ -5922,6 +6078,9 @@ async function main() {
|
|
|
5922
6078
|
await syncAll(force);
|
|
5923
6079
|
return 0;
|
|
5924
6080
|
}
|
|
6081
|
+
case "upload": {
|
|
6082
|
+
return await runUpload(args);
|
|
6083
|
+
}
|
|
5925
6084
|
case "hooks": {
|
|
5926
6085
|
return await runHooksCommand(args, cliEntry);
|
|
5927
6086
|
}
|
|
@@ -6010,7 +6169,7 @@ async function main() {
|
|
|
6010
6169
|
return 1;
|
|
6011
6170
|
}
|
|
6012
6171
|
const resolved = resolveCustomPlanDirPath(dirPath);
|
|
6013
|
-
if (!
|
|
6172
|
+
if (!existsSync13(resolved)) {
|
|
6014
6173
|
writeStderr(`[agendex] path does not exist: ${resolved}`);
|
|
6015
6174
|
return 1;
|
|
6016
6175
|
}
|
|
@@ -6029,7 +6188,7 @@ async function main() {
|
|
|
6029
6188
|
const { request } = await import("node:http");
|
|
6030
6189
|
const body = JSON.stringify({ path: resolved });
|
|
6031
6190
|
try {
|
|
6032
|
-
const res = await new Promise((
|
|
6191
|
+
const res = await new Promise((resolve11, reject) => {
|
|
6033
6192
|
const req = request(`http://localhost:${port}/api/v1/plan-sources`, {
|
|
6034
6193
|
method: "POST",
|
|
6035
6194
|
headers: {
|
|
@@ -6043,7 +6202,7 @@ async function main() {
|
|
|
6043
6202
|
res2.on("data", (chunk) => {
|
|
6044
6203
|
data += chunk;
|
|
6045
6204
|
});
|
|
6046
|
-
res2.on("end", () =>
|
|
6205
|
+
res2.on("end", () => resolve11({ status: res2.statusCode ?? 0, body: data }));
|
|
6047
6206
|
res2.on("error", reject);
|
|
6048
6207
|
});
|
|
6049
6208
|
req.on("error", reject);
|
|
@@ -6203,6 +6362,9 @@ Usage:
|
|
|
6203
6362
|
agendex list-dirs List custom plan directories
|
|
6204
6363
|
agendex sync One-shot scan + sync to cloud (skips unchanged plans)
|
|
6205
6364
|
agendex sync --force Re-sync all plans, ignoring cache
|
|
6365
|
+
agendex upload <path> Upload a single Markdown plan file to the cloud
|
|
6366
|
+
agendex upload <path> --agent <name> Override the uploaded plan's agent label
|
|
6367
|
+
agendex upload <path> --open Open the uploaded plan in the browser after upload
|
|
6206
6368
|
agendex cleanup Interactively remove cloud daemons
|
|
6207
6369
|
agendex cleanup --stale Auto-remove all stale daemons
|
|
6208
6370
|
agendex status Show current config state + daemon status
|
|
@@ -6236,13 +6398,13 @@ function flushStream(stream) {
|
|
|
6236
6398
|
if (stream.destroyed || !stream.writable) {
|
|
6237
6399
|
return Promise.resolve();
|
|
6238
6400
|
}
|
|
6239
|
-
return new Promise((
|
|
6401
|
+
return new Promise((resolve11, reject) => {
|
|
6240
6402
|
stream.write("", (error) => {
|
|
6241
6403
|
if (error) {
|
|
6242
6404
|
reject(error);
|
|
6243
6405
|
return;
|
|
6244
6406
|
}
|
|
6245
|
-
|
|
6407
|
+
resolve11();
|
|
6246
6408
|
});
|
|
6247
6409
|
});
|
|
6248
6410
|
}
|