@warmhub/cli 0.133.0 → 0.134.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/dist/wh.js +122 -19
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -26118,6 +26118,16 @@ function illegalOpSequences(operations, errors, checkAddAdd, options) {
|
|
|
26118
26118
|
}
|
|
26119
26119
|
}
|
|
26120
26120
|
|
|
26121
|
+
// ../../packages/rules/src/reserved-roots.ts
|
|
26122
|
+
var RESERVED_THING_ROOT = "hub";
|
|
26123
|
+
var RESERVED_THING_ROOT_PREFIX = `${RESERVED_THING_ROOT}/`;
|
|
26124
|
+
function isReservedThingRoot(name) {
|
|
26125
|
+
return name === RESERVED_THING_ROOT || name.startsWith(RESERVED_THING_ROOT_PREFIX);
|
|
26126
|
+
}
|
|
26127
|
+
function reservedThingRootMessage(name) {
|
|
26128
|
+
return `Name "${name}" is under the reserved root "${RESERVED_THING_ROOT_PREFIX}"; only Shapes live there, as ${RESERVED_THING_ROOT_PREFIX}shapes/<Name>`;
|
|
26129
|
+
}
|
|
26130
|
+
|
|
26121
26131
|
// ../../packages/rules/src/preflight-operation.ts
|
|
26122
26132
|
var collectionTypes = ["arc", "bond", "set", "list", "pair"];
|
|
26123
26133
|
var canonicalCollectionTypes = ["arc", "bond", "pair", "set", "list"];
|
|
@@ -26133,6 +26143,7 @@ function parseCollectionOp(value) {
|
|
|
26133
26143
|
function preflightOpDiagnostics(op, operationIndex) {
|
|
26134
26144
|
const errors = [];
|
|
26135
26145
|
errors.push(...builtinShapeGuard(op, operationIndex));
|
|
26146
|
+
errors.push(...reservedRootGuard(op, operationIndex));
|
|
26136
26147
|
errors.push(...contentNameGuard(op, operationIndex));
|
|
26137
26148
|
errors.push(...plusSignGuard(op, operationIndex));
|
|
26138
26149
|
errors.push(...validateCollectionAbouts(op, operationIndex));
|
|
@@ -26187,6 +26198,29 @@ function builtinShapeGuard(op, operationIndex) {
|
|
|
26187
26198
|
}
|
|
26188
26199
|
return errors;
|
|
26189
26200
|
}
|
|
26201
|
+
function reservedRootRefusal(name, operationIndex) {
|
|
26202
|
+
return {
|
|
26203
|
+
code: "RESERVED_NAME",
|
|
26204
|
+
operationIndex,
|
|
26205
|
+
message: reservedThingRootMessage(name)
|
|
26206
|
+
};
|
|
26207
|
+
}
|
|
26208
|
+
function reservedRootGuard(op, operationIndex) {
|
|
26209
|
+
if (op.kind === "shape")
|
|
26210
|
+
return [];
|
|
26211
|
+
if (op.operation === "add" && op.name) {
|
|
26212
|
+
const stored = op.kind === "collection" ? op.name : splitLocalPath(op.name)?.bareName;
|
|
26213
|
+
if (stored !== undefined && isReservedThingRoot(stored)) {
|
|
26214
|
+
return [reservedRootRefusal(stored, operationIndex)];
|
|
26215
|
+
}
|
|
26216
|
+
return [];
|
|
26217
|
+
}
|
|
26218
|
+
const isShapeRename = op.name !== undefined && splitLocalPath(op.name) === null;
|
|
26219
|
+
if (op.operation === "rename" && !isShapeRename && op.newName !== undefined && isReservedThingRoot(op.newName)) {
|
|
26220
|
+
return [reservedRootRefusal(op.newName, operationIndex)];
|
|
26221
|
+
}
|
|
26222
|
+
return [];
|
|
26223
|
+
}
|
|
26190
26224
|
function contentNameGuard(op, operationIndex) {
|
|
26191
26225
|
if (op.kind !== "thing" || !op.name)
|
|
26192
26226
|
return [];
|
|
@@ -45429,7 +45463,7 @@ function createStreamingSubmissionHandle(input, deps) {
|
|
|
45429
45463
|
// ../../packages/sdk-ts/package.json
|
|
45430
45464
|
var package_default = {
|
|
45431
45465
|
name: "@warmhub/sdk-ts",
|
|
45432
|
-
version: "0.
|
|
45466
|
+
version: "0.132.0",
|
|
45433
45467
|
private: false,
|
|
45434
45468
|
type: "module",
|
|
45435
45469
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -49791,10 +49825,10 @@ class WorkOsAuthError extends Error {
|
|
|
49791
49825
|
this.status = status;
|
|
49792
49826
|
}
|
|
49793
49827
|
}
|
|
49794
|
-
async function refreshAccessToken(tokens, signal) {
|
|
49828
|
+
async function refreshAccessToken(tokens, signal, options = {}) {
|
|
49795
49829
|
const log = getLog();
|
|
49796
49830
|
const { clientId } = tokens;
|
|
49797
|
-
const workosUrl = "https://api.workos.com";
|
|
49831
|
+
const workosUrl = (options.workosUrl ?? "https://api.workos.com").replace(/\/$/, "");
|
|
49798
49832
|
const path = "/user_management/authenticate";
|
|
49799
49833
|
const requestId = `${process.pid}-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
49800
49834
|
log.debug("http.request", {
|
|
@@ -49804,7 +49838,8 @@ async function refreshAccessToken(tokens, signal) {
|
|
|
49804
49838
|
request_id: requestId
|
|
49805
49839
|
});
|
|
49806
49840
|
const startedAt = Date.now();
|
|
49807
|
-
const
|
|
49841
|
+
const timeoutSignal = AbortSignal.timeout(options.requestTimeoutMs ?? WORKOS_REFRESH_TIMEOUT_MS);
|
|
49842
|
+
const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
49808
49843
|
let res;
|
|
49809
49844
|
try {
|
|
49810
49845
|
res = await fetch(`${workosUrl}${path}`, {
|
|
@@ -50379,6 +50414,9 @@ function corruptedAuthError(path, cause) {
|
|
|
50379
50414
|
}
|
|
50380
50415
|
|
|
50381
50416
|
// ../../packages/warmhub-cli/src/auth.ts
|
|
50417
|
+
var AUTH_REFRESH_BUDGET_MS = 30000;
|
|
50418
|
+
var AUTH_REFRESH_RETRY_DELAY_MS = 1000;
|
|
50419
|
+
var TRANSIENT_REFRESH_COOLDOWN_MS = 5000;
|
|
50382
50420
|
function isAuthLockError(error51, authPath) {
|
|
50383
50421
|
return error51 instanceof Error && error51.code === "ELOCKED" && (error51.file === undefined || error51.file === authPath);
|
|
50384
50422
|
}
|
|
@@ -50400,6 +50438,17 @@ function delay2(ms, signal) {
|
|
|
50400
50438
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
50401
50439
|
});
|
|
50402
50440
|
}
|
|
50441
|
+
function refreshCooldownActive(failedAt) {
|
|
50442
|
+
if (!failedAt)
|
|
50443
|
+
return false;
|
|
50444
|
+
const ageMs = Date.now() - new Date(failedAt).getTime();
|
|
50445
|
+
return ageMs >= 0 && ageMs < TRANSIENT_REFRESH_COOLDOWN_MS;
|
|
50446
|
+
}
|
|
50447
|
+
function withoutRefreshFailure(profile) {
|
|
50448
|
+
const next = { ...profile };
|
|
50449
|
+
delete next.transientRefreshFailedAt;
|
|
50450
|
+
return next;
|
|
50451
|
+
}
|
|
50403
50452
|
function getTokenInfo(profile) {
|
|
50404
50453
|
const envToken = process.env.WH_TOKEN;
|
|
50405
50454
|
if (envToken) {
|
|
@@ -50428,7 +50477,7 @@ function getTokenInfo(profile) {
|
|
|
50428
50477
|
canRefresh: source === "device" && !!tokens.refreshToken
|
|
50429
50478
|
};
|
|
50430
50479
|
}
|
|
50431
|
-
async function getValidToken(profile, signal) {
|
|
50480
|
+
async function getValidToken(profile, signal, options = {}) {
|
|
50432
50481
|
const log = getLog();
|
|
50433
50482
|
const envToken = process.env.WH_TOKEN;
|
|
50434
50483
|
if (envToken) {
|
|
@@ -50460,7 +50509,10 @@ async function getValidToken(profile, signal) {
|
|
|
50460
50509
|
const classification = err.error === "invalid_grant" ? "invalid_grant" : "terminal";
|
|
50461
50510
|
const staleProf = getProfile(profileName, authPath);
|
|
50462
50511
|
if (staleProf) {
|
|
50463
|
-
saveProfileWhileLocked(profileName, {
|
|
50512
|
+
saveProfileWhileLocked(profileName, withoutRefreshFailure({
|
|
50513
|
+
...staleProf,
|
|
50514
|
+
tokens: { ...staleProf.tokens, refreshToken: "" }
|
|
50515
|
+
}), authPath);
|
|
50464
50516
|
log.error("auth.refresh_token.wiped", {
|
|
50465
50517
|
profile: profileName,
|
|
50466
50518
|
reason: classification
|
|
@@ -50472,6 +50524,16 @@ async function getValidToken(profile, signal) {
|
|
|
50472
50524
|
}
|
|
50473
50525
|
throw new CliError(5 /* Auth */, "AUTH", `Session could not be refreshed (${err.error}).${err.errorDescription ? ` ${err.errorDescription}` : ""}`, err, `Run ${loginCmd} to re-authenticate.`);
|
|
50474
50526
|
};
|
|
50527
|
+
const transientRefreshError = (cause) => new CliError(5 /* Auth */, "AUTH", "Token refresh failed (transient).", cause, `Check network connectivity, or run ${loginCmd} to re-authenticate.`);
|
|
50528
|
+
const markTransientRefreshFailure = () => {
|
|
50529
|
+
const failedProf = getProfile(profileName, authPath);
|
|
50530
|
+
if (!failedProf)
|
|
50531
|
+
return;
|
|
50532
|
+
saveProfileWhileLocked(profileName, {
|
|
50533
|
+
...failedProf,
|
|
50534
|
+
transientRefreshFailedAt: new Date().toISOString()
|
|
50535
|
+
}, authPath);
|
|
50536
|
+
};
|
|
50475
50537
|
try {
|
|
50476
50538
|
return await withAuthLock(authPath, async () => {
|
|
50477
50539
|
const lockedProf = getProfile(profileName, authPath);
|
|
@@ -50486,14 +50548,20 @@ async function getValidToken(profile, signal) {
|
|
|
50486
50548
|
if (!lockedTokens.refreshToken) {
|
|
50487
50549
|
throw new CliError(5 /* Auth */, "AUTH", "Session expired.", undefined, `Run ${loginCmd} to re-authenticate.`);
|
|
50488
50550
|
}
|
|
50551
|
+
if (refreshCooldownActive(lockedProf.transientRefreshFailedAt)) {
|
|
50552
|
+
log.info("auth.refresh.cooldown", { profile: profileName });
|
|
50553
|
+
throw transientRefreshError();
|
|
50554
|
+
}
|
|
50555
|
+
const budgetSignal = AbortSignal.timeout(options.refreshBudgetMs ?? AUTH_REFRESH_BUDGET_MS);
|
|
50556
|
+
const refreshSignal = signal ? AbortSignal.any([signal, budgetSignal]) : budgetSignal;
|
|
50489
50557
|
const refreshStarted = Date.now();
|
|
50490
50558
|
log.info("auth.refresh.start", {
|
|
50491
50559
|
profile: profileName,
|
|
50492
50560
|
client_id: lockedTokens.clientId
|
|
50493
50561
|
});
|
|
50494
50562
|
try {
|
|
50495
|
-
const refreshed = await refreshAccessToken(lockedTokens,
|
|
50496
|
-
saveProfileWhileLocked(profileName, { ...lockedProf, tokens: refreshed }, authPath);
|
|
50563
|
+
const refreshed = await refreshAccessToken(lockedTokens, refreshSignal);
|
|
50564
|
+
saveProfileWhileLocked(profileName, withoutRefreshFailure({ ...lockedProf, tokens: refreshed }), authPath);
|
|
50497
50565
|
log.info("auth.refresh.ok", {
|
|
50498
50566
|
profile: profileName,
|
|
50499
50567
|
duration_ms: Date.now() - refreshStarted,
|
|
@@ -50521,15 +50589,25 @@ async function getValidToken(profile, signal) {
|
|
|
50521
50589
|
duration_ms: Date.now() - refreshStarted,
|
|
50522
50590
|
error_name: err instanceof Error ? err.name : "Unknown"
|
|
50523
50591
|
});
|
|
50524
|
-
|
|
50592
|
+
try {
|
|
50593
|
+
await delay2(options.retryDelayMs ?? AUTH_REFRESH_RETRY_DELAY_MS, refreshSignal);
|
|
50594
|
+
} catch (delayErr) {
|
|
50595
|
+
if (signal?.aborted)
|
|
50596
|
+
throw delayErr;
|
|
50597
|
+
markTransientRefreshFailure();
|
|
50598
|
+
throw transientRefreshError(delayErr);
|
|
50599
|
+
}
|
|
50525
50600
|
log.info("auth.refresh.retry", { profile: profileName, attempt: 2 });
|
|
50526
50601
|
let retryStarted = Date.now();
|
|
50527
50602
|
try {
|
|
50528
50603
|
const retryProf = getProfile(profileName, authPath);
|
|
50529
50604
|
const retryTokens = retryProf?.tokens ?? lockedTokens;
|
|
50530
50605
|
retryStarted = Date.now();
|
|
50531
|
-
const refreshed = await refreshAccessToken(retryTokens,
|
|
50532
|
-
saveProfileWhileLocked(profileName, {
|
|
50606
|
+
const refreshed = await refreshAccessToken(retryTokens, refreshSignal);
|
|
50607
|
+
saveProfileWhileLocked(profileName, withoutRefreshFailure({
|
|
50608
|
+
...retryProf ?? lockedProf,
|
|
50609
|
+
tokens: refreshed
|
|
50610
|
+
}), authPath);
|
|
50533
50611
|
log.info("auth.refresh.ok", {
|
|
50534
50612
|
profile: profileName,
|
|
50535
50613
|
duration_ms: Date.now() - retryStarted,
|
|
@@ -50554,7 +50632,8 @@ async function getValidToken(profile, signal) {
|
|
|
50554
50632
|
failTerminalRefresh(retryErr);
|
|
50555
50633
|
}
|
|
50556
50634
|
log.info("auth.refresh.failed", fields);
|
|
50557
|
-
|
|
50635
|
+
markTransientRefreshFailure();
|
|
50636
|
+
throw transientRefreshError(retryErr);
|
|
50558
50637
|
}
|
|
50559
50638
|
}
|
|
50560
50639
|
});
|
|
@@ -50873,7 +50952,7 @@ function shouldGuardDomain(domainPath, canonicalVerb, args) {
|
|
|
50873
50952
|
}
|
|
50874
50953
|
async function probeCapabilities(ctx) {
|
|
50875
50954
|
try {
|
|
50876
|
-
return await ctx.client.diagnostics.capabilities();
|
|
50955
|
+
return await (ctx.compatibilityClient ?? ctx.client).diagnostics.capabilities();
|
|
50877
50956
|
} catch {
|
|
50878
50957
|
return;
|
|
50879
50958
|
}
|
|
@@ -50887,7 +50966,7 @@ async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
|
|
|
50887
50966
|
}
|
|
50888
50967
|
let capabilities;
|
|
50889
50968
|
try {
|
|
50890
|
-
const diagnostics = ctx.client.diagnostics;
|
|
50969
|
+
const diagnostics = (ctx.compatibilityClient ?? ctx.client).diagnostics;
|
|
50891
50970
|
if (typeof diagnostics.assertCompatible === "function") {
|
|
50892
50971
|
await diagnostics.assertCompatible();
|
|
50893
50972
|
if (clientFlags.length > 0)
|
|
@@ -50896,6 +50975,8 @@ async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
|
|
|
50896
50975
|
capabilities = await diagnostics.capabilities();
|
|
50897
50976
|
}
|
|
50898
50977
|
} catch (err) {
|
|
50978
|
+
if (err instanceof CliError && err.kind === "AUTH")
|
|
50979
|
+
throw err;
|
|
50899
50980
|
const message = err instanceof Error ? err.message : String(err);
|
|
50900
50981
|
if (message.includes("Could not find") || message.includes("NOT_FOUND") || message.includes("is not a function")) {
|
|
50901
50982
|
ctx.err("Backend does not support capabilities check (upgrade backend)");
|
|
@@ -55552,7 +55633,20 @@ Run \`wh auth login --profile ${explicitProfile}\` to create it.`);
|
|
|
55552
55633
|
clientFlags,
|
|
55553
55634
|
decorateResponses: decorate
|
|
55554
55635
|
});
|
|
55555
|
-
|
|
55636
|
+
const compatibilityClient = args.client ?? createUnauthenticatedClient(config2, {
|
|
55637
|
+
functionLogs: args.functionLogs,
|
|
55638
|
+
signal: args.signal,
|
|
55639
|
+
clientFlags,
|
|
55640
|
+
decorateResponses: decorate
|
|
55641
|
+
});
|
|
55642
|
+
return {
|
|
55643
|
+
config: config2,
|
|
55644
|
+
profile: effectiveProfile,
|
|
55645
|
+
client,
|
|
55646
|
+
compatibilityClient,
|
|
55647
|
+
clientFlags,
|
|
55648
|
+
decorate
|
|
55649
|
+
};
|
|
55556
55650
|
}
|
|
55557
55651
|
|
|
55558
55652
|
// ../../packages/warmhub-cli/src/domains/auth-shared.ts
|
|
@@ -69712,9 +69806,17 @@ async function runPreparedCli(rawArgv, prepared, opts) {
|
|
|
69712
69806
|
requestedMode: requestedFunctionLogs
|
|
69713
69807
|
});
|
|
69714
69808
|
const localOnlyCommand = isLocalOnlyInvocation(invocation);
|
|
69715
|
-
const {
|
|
69809
|
+
const {
|
|
69810
|
+
config: config2,
|
|
69811
|
+
client,
|
|
69812
|
+
compatibilityClient,
|
|
69813
|
+
profile,
|
|
69814
|
+
clientFlags,
|
|
69815
|
+
decorate
|
|
69816
|
+
} = localOnlyCommand ? {
|
|
69716
69817
|
config: loadConfig(),
|
|
69717
69818
|
client: createLocalOnlyClient(),
|
|
69819
|
+
compatibilityClient: undefined,
|
|
69718
69820
|
profile: "default",
|
|
69719
69821
|
clientFlags: [],
|
|
69720
69822
|
decorate: true
|
|
@@ -69735,6 +69837,7 @@ async function runPreparedCli(rawArgv, prepared, opts) {
|
|
|
69735
69837
|
const signal = abortController.signal;
|
|
69736
69838
|
const commandContext = {
|
|
69737
69839
|
client,
|
|
69840
|
+
compatibilityClient,
|
|
69738
69841
|
config: config2,
|
|
69739
69842
|
invocation,
|
|
69740
69843
|
profile,
|
|
@@ -69861,7 +69964,7 @@ function resolveLogLevel(flagLevel, env) {
|
|
|
69861
69964
|
// package.json
|
|
69862
69965
|
var package_default3 = {
|
|
69863
69966
|
name: "@warmhub/cli",
|
|
69864
|
-
version: "0.
|
|
69967
|
+
version: "0.134.0",
|
|
69865
69968
|
private: false,
|
|
69866
69969
|
type: "module",
|
|
69867
69970
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -70486,5 +70589,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
|
|
|
70486
70589
|
version: package_default3.version
|
|
70487
70590
|
}) : interceptedExitCode;
|
|
70488
70591
|
|
|
70489
|
-
//# debugId=
|
|
70490
|
-
//# warmhub-cli-build-info {"cliVersion":"0.
|
|
70592
|
+
//# debugId=59E58BA2C90F5E3C64756E2164756E21
|
|
70593
|
+
//# warmhub-cli-build-info {"cliVersion":"0.134.0","sdkVersion":"0.132.0"}
|
package/package.json
CHANGED