@crabcloud/cli 0.1.9 → 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/dist/crab.js +344 -3
- package/dist/skills/crabcloud/SKILL.md +7 -0
- package/package.json +2 -2
package/dist/crab.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
2
16
|
|
|
3
17
|
// src/index.ts
|
|
4
18
|
import { hostname, homedir as homedir2 } from "node:os";
|
|
@@ -980,6 +994,7 @@ function datetime(args) {
|
|
|
980
994
|
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
|
|
981
995
|
}
|
|
982
996
|
var anyString = /^[\s\S]{0,}$/;
|
|
997
|
+
var bigint = /^-?\d+n?$/;
|
|
983
998
|
var integer = /^-?\d+$/;
|
|
984
999
|
var number = /^-?\d+(?:\.\d+)?$/;
|
|
985
1000
|
var boolean = /^(?:true|false)$/i;
|
|
@@ -1885,6 +1900,25 @@ var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
|
1885
1900
|
return payload;
|
|
1886
1901
|
};
|
|
1887
1902
|
});
|
|
1903
|
+
var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
|
|
1904
|
+
$ZodType.init(inst, def);
|
|
1905
|
+
inst._zod.pattern = bigint;
|
|
1906
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1907
|
+
if (def.coerce)
|
|
1908
|
+
try {
|
|
1909
|
+
payload.value = BigInt(payload.value);
|
|
1910
|
+
} catch (_) {}
|
|
1911
|
+
if (typeof payload.value === "bigint")
|
|
1912
|
+
return payload;
|
|
1913
|
+
payload.issues.push({
|
|
1914
|
+
expected: "bigint",
|
|
1915
|
+
code: "invalid_type",
|
|
1916
|
+
input: payload.value,
|
|
1917
|
+
inst
|
|
1918
|
+
});
|
|
1919
|
+
return payload;
|
|
1920
|
+
};
|
|
1921
|
+
});
|
|
1888
1922
|
var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
1889
1923
|
$ZodType.init(inst, def);
|
|
1890
1924
|
inst._zod.pattern = _null;
|
|
@@ -1918,6 +1952,29 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
|
|
|
1918
1952
|
return payload;
|
|
1919
1953
|
};
|
|
1920
1954
|
});
|
|
1955
|
+
var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
1956
|
+
$ZodType.init(inst, def);
|
|
1957
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1958
|
+
if (def.coerce) {
|
|
1959
|
+
try {
|
|
1960
|
+
payload.value = new Date(payload.value);
|
|
1961
|
+
} catch (_err) {}
|
|
1962
|
+
}
|
|
1963
|
+
const input = payload.value;
|
|
1964
|
+
const isDate = input instanceof Date;
|
|
1965
|
+
const isValidDate = isDate && !Number.isNaN(input.getTime());
|
|
1966
|
+
if (isValidDate)
|
|
1967
|
+
return payload;
|
|
1968
|
+
payload.issues.push({
|
|
1969
|
+
expected: "date",
|
|
1970
|
+
code: "invalid_type",
|
|
1971
|
+
input,
|
|
1972
|
+
...isDate ? { received: "Invalid Date" } : {},
|
|
1973
|
+
inst
|
|
1974
|
+
});
|
|
1975
|
+
return payload;
|
|
1976
|
+
};
|
|
1977
|
+
});
|
|
1921
1978
|
function handleArrayResult(result, final, index) {
|
|
1922
1979
|
if (result.issues.length) {
|
|
1923
1980
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -3323,6 +3380,9 @@ function snapshotChecks(def) {
|
|
|
3323
3380
|
function _string(Class, params) {
|
|
3324
3381
|
return new Class(snapshotChecks({ type: "string", ...normalizeParams(params) }));
|
|
3325
3382
|
}
|
|
3383
|
+
function _coercedString(Class, params) {
|
|
3384
|
+
return new Class(snapshotChecks({ type: "string", coerce: true, ...normalizeParams(params) }));
|
|
3385
|
+
}
|
|
3326
3386
|
function _email(Class, params) {
|
|
3327
3387
|
return new Class({
|
|
3328
3388
|
type: "string",
|
|
@@ -3563,6 +3623,9 @@ function _isoDuration(Class, params) {
|
|
|
3563
3623
|
function _number(Class, params) {
|
|
3564
3624
|
return new Class(snapshotChecks({ type: "number", checks: [], ...normalizeParams(params) }));
|
|
3565
3625
|
}
|
|
3626
|
+
function _coercedNumber(Class, params) {
|
|
3627
|
+
return new Class(snapshotChecks({ type: "number", coerce: true, checks: [], ...normalizeParams(params) }));
|
|
3628
|
+
}
|
|
3566
3629
|
function _int(Class, params) {
|
|
3567
3630
|
return new Class({
|
|
3568
3631
|
type: "number",
|
|
@@ -3578,6 +3641,20 @@ function _boolean(Class, params) {
|
|
|
3578
3641
|
...normalizeParams(params)
|
|
3579
3642
|
});
|
|
3580
3643
|
}
|
|
3644
|
+
function _coercedBoolean(Class, params) {
|
|
3645
|
+
return new Class({
|
|
3646
|
+
type: "boolean",
|
|
3647
|
+
coerce: true,
|
|
3648
|
+
...normalizeParams(params)
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
function _coercedBigint(Class, params) {
|
|
3652
|
+
return new Class({
|
|
3653
|
+
type: "bigint",
|
|
3654
|
+
coerce: true,
|
|
3655
|
+
...normalizeParams(params)
|
|
3656
|
+
});
|
|
3657
|
+
}
|
|
3581
3658
|
function _null2(Class, params) {
|
|
3582
3659
|
return new Class({
|
|
3583
3660
|
type: "null",
|
|
@@ -3595,6 +3672,13 @@ function _never(Class, params) {
|
|
|
3595
3672
|
...normalizeParams(params)
|
|
3596
3673
|
});
|
|
3597
3674
|
}
|
|
3675
|
+
function _coercedDate(Class, params) {
|
|
3676
|
+
return new Class({
|
|
3677
|
+
type: "date",
|
|
3678
|
+
coerce: true,
|
|
3679
|
+
...normalizeParams(params)
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3598
3682
|
function _lt(value, params) {
|
|
3599
3683
|
return new $ZodCheckLessThan({
|
|
3600
3684
|
check: "less_than",
|
|
@@ -4469,6 +4553,9 @@ var numberProcessor = (schema, ctx, _json, params) => {
|
|
|
4469
4553
|
var booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
4470
4554
|
json.type = "boolean";
|
|
4471
4555
|
};
|
|
4556
|
+
var bigintProcessor = (schema, ctx, json, params) => {
|
|
4557
|
+
handleUnrepresentable(schema, ctx, json, params, "BigInt cannot be represented in JSON Schema");
|
|
4558
|
+
};
|
|
4472
4559
|
var nullProcessor = (_schema, ctx, json, _params) => {
|
|
4473
4560
|
if (ctx.target === "openapi-3.0") {
|
|
4474
4561
|
json.type = "string";
|
|
@@ -4482,6 +4569,9 @@ var neverProcessor = (_schema, _ctx, json, _params) => {
|
|
|
4482
4569
|
json.not = {};
|
|
4483
4570
|
};
|
|
4484
4571
|
var unknownProcessor = (_schema, _ctx, _json, _params) => {};
|
|
4572
|
+
var dateProcessor = (schema, ctx, json, params) => {
|
|
4573
|
+
handleUnrepresentable(schema, ctx, json, params, "Date cannot be represented in JSON Schema");
|
|
4574
|
+
};
|
|
4485
4575
|
var enumProcessor = (schema, _ctx, json, _params) => {
|
|
4486
4576
|
const def = schema._zod.def;
|
|
4487
4577
|
const values = getEnumValues(def.entries);
|
|
@@ -5346,6 +5436,49 @@ var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
|
5346
5436
|
function boolean2(params) {
|
|
5347
5437
|
return _boolean(ZodBoolean, params);
|
|
5348
5438
|
}
|
|
5439
|
+
var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
|
|
5440
|
+
$ZodBigInt.init(inst, def);
|
|
5441
|
+
ZodType.init(inst, def);
|
|
5442
|
+
inst._zod.processJSONSchema = (ctx, json, params) => bigintProcessor(inst, ctx, json, params);
|
|
5443
|
+
}, /* @__PURE__ */ derived({
|
|
5444
|
+
minValue: (inst) => aggregateChecks(inst).minimum ?? null,
|
|
5445
|
+
maxValue: (inst) => aggregateChecks(inst).maximum ?? null,
|
|
5446
|
+
format: (inst) => aggregateChecks(inst).format ?? null
|
|
5447
|
+
}, {
|
|
5448
|
+
gte(value, params) {
|
|
5449
|
+
return this.check(_gte(value, params));
|
|
5450
|
+
},
|
|
5451
|
+
min(value, params) {
|
|
5452
|
+
return this.check(_gte(value, params));
|
|
5453
|
+
},
|
|
5454
|
+
gt(value, params) {
|
|
5455
|
+
return this.check(_gt(value, params));
|
|
5456
|
+
},
|
|
5457
|
+
lt(value, params) {
|
|
5458
|
+
return this.check(_lt(value, params));
|
|
5459
|
+
},
|
|
5460
|
+
lte(value, params) {
|
|
5461
|
+
return this.check(_lte(value, params));
|
|
5462
|
+
},
|
|
5463
|
+
max(value, params) {
|
|
5464
|
+
return this.check(_lte(value, params));
|
|
5465
|
+
},
|
|
5466
|
+
positive(params) {
|
|
5467
|
+
return this.check(_gt(BigInt(0), params));
|
|
5468
|
+
},
|
|
5469
|
+
negative(params) {
|
|
5470
|
+
return this.check(_lt(BigInt(0), params));
|
|
5471
|
+
},
|
|
5472
|
+
nonpositive(params) {
|
|
5473
|
+
return this.check(_lte(BigInt(0), params));
|
|
5474
|
+
},
|
|
5475
|
+
nonnegative(params) {
|
|
5476
|
+
return this.check(_gte(BigInt(0), params));
|
|
5477
|
+
},
|
|
5478
|
+
multipleOf(value, params) {
|
|
5479
|
+
return this.check(_multipleOf(value, params));
|
|
5480
|
+
}
|
|
5481
|
+
}));
|
|
5349
5482
|
var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
5350
5483
|
$ZodNull.init(inst, def);
|
|
5351
5484
|
ZodType.init(inst, def);
|
|
@@ -5370,6 +5503,22 @@ var ZodNever = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
|
|
|
5370
5503
|
function never(params) {
|
|
5371
5504
|
return _never(ZodNever, params);
|
|
5372
5505
|
}
|
|
5506
|
+
var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
|
|
5507
|
+
$ZodDate.init(inst, def);
|
|
5508
|
+
ZodType.init(inst, def);
|
|
5509
|
+
inst._zod.processJSONSchema = (ctx, json, params) => dateProcessor(inst, ctx, json, params);
|
|
5510
|
+
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
5511
|
+
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
5512
|
+
}, /* @__PURE__ */ derived({
|
|
5513
|
+
minDate: (inst) => {
|
|
5514
|
+
const { minimum } = aggregateChecks(inst);
|
|
5515
|
+
return minimum ? new Date(minimum) : null;
|
|
5516
|
+
},
|
|
5517
|
+
maxDate: (inst) => {
|
|
5518
|
+
const { maximum } = aggregateChecks(inst);
|
|
5519
|
+
return maximum ? new Date(maximum) : null;
|
|
5520
|
+
}
|
|
5521
|
+
}, {}));
|
|
5373
5522
|
var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
5374
5523
|
_ensureDefaultMemoizer();
|
|
5375
5524
|
$ZodArray.init(inst, def);
|
|
@@ -5720,6 +5869,30 @@ function refine(fn, _params = {}) {
|
|
|
5720
5869
|
function superRefine(fn, params) {
|
|
5721
5870
|
return _superRefine(fn, params);
|
|
5722
5871
|
}
|
|
5872
|
+
// ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/coerce.js
|
|
5873
|
+
var exports_coerce = {};
|
|
5874
|
+
__export(exports_coerce, {
|
|
5875
|
+
bigint: () => bigint2,
|
|
5876
|
+
boolean: () => boolean3,
|
|
5877
|
+
date: () => date2,
|
|
5878
|
+
number: () => number3,
|
|
5879
|
+
string: () => string3
|
|
5880
|
+
});
|
|
5881
|
+
function string3(params) {
|
|
5882
|
+
return _coercedString(ZodString, params);
|
|
5883
|
+
}
|
|
5884
|
+
function number3(params) {
|
|
5885
|
+
return _coercedNumber(ZodNumber, params);
|
|
5886
|
+
}
|
|
5887
|
+
function boolean3(params) {
|
|
5888
|
+
return _coercedBoolean(ZodBoolean, params);
|
|
5889
|
+
}
|
|
5890
|
+
function bigint2(params) {
|
|
5891
|
+
return _coercedBigint(ZodBigInt, params);
|
|
5892
|
+
}
|
|
5893
|
+
function date2(params) {
|
|
5894
|
+
return _coercedDate(ZodDate, params);
|
|
5895
|
+
}
|
|
5723
5896
|
// ../../packages/contracts/src/index.ts
|
|
5724
5897
|
var accountDomain = "crabcloud.cc";
|
|
5725
5898
|
var adminDomain = `admin.${accountDomain}`;
|
|
@@ -5773,6 +5946,8 @@ var apiErrorSchema = object({
|
|
|
5773
5946
|
"expired",
|
|
5774
5947
|
"insufficient_credits",
|
|
5775
5948
|
"payload_too_large",
|
|
5949
|
+
"collab_space_not_bound",
|
|
5950
|
+
"collab_space_mismatch",
|
|
5776
5951
|
"internal"
|
|
5777
5952
|
]),
|
|
5778
5953
|
message: string2()
|
|
@@ -5827,7 +6002,8 @@ var sessionSummarySchema = object({
|
|
|
5827
6002
|
});
|
|
5828
6003
|
var deviceStartInput = object({
|
|
5829
6004
|
name: string2().trim().min(1).max(80),
|
|
5830
|
-
scopes: array(_enum(scopes)).min(1).max(scopes.length)
|
|
6005
|
+
scopes: array(_enum(scopes)).min(1).max(scopes.length),
|
|
6006
|
+
space: string2().trim().min(1).max(80).optional()
|
|
5831
6007
|
});
|
|
5832
6008
|
var devicePollInput = object({ deviceCode: string2().min(16).max(200) });
|
|
5833
6009
|
var deviceDecisionInput = object({
|
|
@@ -5839,6 +6015,7 @@ var agentTokenSummarySchema = object({
|
|
|
5839
6015
|
id: string2(),
|
|
5840
6016
|
name: string2(),
|
|
5841
6017
|
scopes: array(_enum(scopes)),
|
|
6018
|
+
collabSpace: string2().nullable().optional(),
|
|
5842
6019
|
createdAt: number2(),
|
|
5843
6020
|
lastUsedAt: number2().nullable(),
|
|
5844
6021
|
expiresAt: number2().nullable(),
|
|
@@ -5886,6 +6063,13 @@ var adminPlanTierUpdateInput = object({
|
|
|
5886
6063
|
quotaJson: record(string2(), unknown()).optional(),
|
|
5887
6064
|
status: _enum(adminPlanTierStatuses).optional()
|
|
5888
6065
|
});
|
|
6066
|
+
var subscriptionChangeInput = object({
|
|
6067
|
+
tierId: string2().trim().min(1).max(50)
|
|
6068
|
+
});
|
|
6069
|
+
var adminUserSubscriptionInput = object({
|
|
6070
|
+
tierId: string2().trim().min(1).max(50),
|
|
6071
|
+
reason: string2().trim().min(1).max(500)
|
|
6072
|
+
});
|
|
5889
6073
|
var giftFulfillments = ["stock", "webhook"];
|
|
5890
6074
|
var giftMerchantStatuses = ["active", "disabled"];
|
|
5891
6075
|
var giftProductStatuses = ["draft", "live", "delisted"];
|
|
@@ -5990,6 +6174,49 @@ var contactQueryInput = object({
|
|
|
5990
6174
|
limit: number2().int().min(1).max(50).default(20),
|
|
5991
6175
|
offset: number2().int().min(0).default(0)
|
|
5992
6176
|
});
|
|
6177
|
+
var collabTaskStatuses = ["open", "done"];
|
|
6178
|
+
var collabBoostKinds = ["tasks", "members"];
|
|
6179
|
+
var COLLAB_RECORD_BODY_MAX = 20000;
|
|
6180
|
+
var COLLAB_RECORD_FILES_MAX = 10;
|
|
6181
|
+
var COLLAB_RECORD_LINKS_MAX = 10;
|
|
6182
|
+
var COLLAB_TITLE_MAX = 200;
|
|
6183
|
+
var COLLAB_SPACE_NAME_MAX = 64;
|
|
6184
|
+
var COLLAB_SUMMARY_MAX = 2000;
|
|
6185
|
+
var collabCreateSpaceInput = object({
|
|
6186
|
+
name: string2().trim().min(1).max(COLLAB_SPACE_NAME_MAX),
|
|
6187
|
+
allocationBytes: number2().int().min(1).max(10 * 1024 * 1024 * 1024).optional()
|
|
6188
|
+
});
|
|
6189
|
+
var collabRenameSpaceInput = object({ name: string2().trim().min(1).max(COLLAB_SPACE_NAME_MAX) });
|
|
6190
|
+
var collabAllocationInput = object({
|
|
6191
|
+
allocationBytes: number2().int().min(1).max(10 * 1024 * 1024 * 1024)
|
|
6192
|
+
});
|
|
6193
|
+
var collabBoostInput = object({ kind: _enum(collabBoostKinds) });
|
|
6194
|
+
var collabInviteInput = object({ username: usernameSchema });
|
|
6195
|
+
var collabLinkInput = string2().trim().url().max(2000);
|
|
6196
|
+
var collabCreateTaskInput = object({
|
|
6197
|
+
title: string2().trim().min(1).max(COLLAB_TITLE_MAX),
|
|
6198
|
+
body: string2().max(COLLAB_RECORD_BODY_MAX).default(""),
|
|
6199
|
+
fileIds: array(string2().trim().min(1).max(64)).max(COLLAB_RECORD_FILES_MAX).optional(),
|
|
6200
|
+
links: array(collabLinkInput).max(COLLAB_RECORD_LINKS_MAX).optional()
|
|
6201
|
+
});
|
|
6202
|
+
var collabPushRecordInput = object({
|
|
6203
|
+
body: string2().min(1).max(COLLAB_RECORD_BODY_MAX),
|
|
6204
|
+
fileIds: array(string2().trim().min(1).max(64)).max(COLLAB_RECORD_FILES_MAX).optional(),
|
|
6205
|
+
links: array(collabLinkInput).max(COLLAB_RECORD_LINKS_MAX).optional()
|
|
6206
|
+
});
|
|
6207
|
+
var collabUpdateSummaryInput = object({
|
|
6208
|
+
summary: string2().trim().max(COLLAB_SUMMARY_MAX)
|
|
6209
|
+
});
|
|
6210
|
+
var collabTaskListQuery = object({
|
|
6211
|
+
status: _enum(collabTaskStatuses).optional(),
|
|
6212
|
+
q: string2().trim().max(200).optional(),
|
|
6213
|
+
cursor: string2().trim().max(200).optional(),
|
|
6214
|
+
limit: exports_coerce.number().int().min(1).max(100).optional()
|
|
6215
|
+
});
|
|
6216
|
+
var collabRecordListQuery = object({
|
|
6217
|
+
cursor: string2().trim().max(200).optional(),
|
|
6218
|
+
limit: exports_coerce.number().int().min(1).max(200).optional()
|
|
6219
|
+
});
|
|
5993
6220
|
|
|
5994
6221
|
// ../../packages/cloudkit/src/crypto.ts
|
|
5995
6222
|
var enc = new TextEncoder;
|
|
@@ -6309,6 +6536,9 @@ function requireCredentials() {
|
|
|
6309
6536
|
function formatTime(ms) {
|
|
6310
6537
|
return new Date(ms).toLocaleString("sv", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
|
|
6311
6538
|
}
|
|
6539
|
+
function fmtCredits(cents) {
|
|
6540
|
+
return cents.toLocaleString("en-US");
|
|
6541
|
+
}
|
|
6312
6542
|
var usage = `crab — Crab Cloud CLI(Agent-first 入口)
|
|
6313
6543
|
发布物经 npm 分发:npx @crabcloud/cli <command>(全局安装后短名 crab 等价)
|
|
6314
6544
|
|
|
@@ -6371,6 +6601,10 @@ var usage = `crab — Crab Cloud CLI(Agent-first 入口)
|
|
|
6371
6601
|
storage categories [--json] 分类列表
|
|
6372
6602
|
storage mkcat <名称> 新建分类
|
|
6373
6603
|
storage tags [--json] 标签汇总
|
|
6604
|
+
credits [--json] 积分余额(月送/充值/合计;需 credits.read scope)
|
|
6605
|
+
credits history [--limit N] [--offset N] [--json]
|
|
6606
|
+
积分流水(变动 ±:消耗为负;需 credits.read)
|
|
6607
|
+
credits pricing [--json] 动作计价标准(公开:动作单价/档位/充值包)
|
|
6374
6608
|
skills install|list|uninstall [--agent claude,zcode,codex,agents]
|
|
6375
6609
|
skills 管理(claude/zcode/agents 复制目录,codex 写 AGENTS.md 段)
|
|
6376
6610
|
logout 撤销当前 Agent Token 并清除本地凭证
|
|
@@ -6473,11 +6707,105 @@ async function whoami() {
|
|
|
6473
6707
|
if (subscription)
|
|
6474
6708
|
console.log(` 订阅: ${subscription.tier_name}`);
|
|
6475
6709
|
if (credits !== undefined)
|
|
6476
|
-
console.log(` 积分余额:
|
|
6710
|
+
console.log(` 积分余额: ${fmtCredits(credits)} 积分`);
|
|
6477
6711
|
if (apps?.length)
|
|
6478
6712
|
console.log(` 已启用应用: ${apps.map((a) => a.title).join("、")}`);
|
|
6479
6713
|
return 0;
|
|
6480
6714
|
}
|
|
6715
|
+
var CREDIT_REASON_LABELS = {
|
|
6716
|
+
subscription_grant: "月送发放",
|
|
6717
|
+
topup: "充值入账",
|
|
6718
|
+
consume: "动作消耗",
|
|
6719
|
+
refund: "退款",
|
|
6720
|
+
adjustment: "人工调整"
|
|
6721
|
+
};
|
|
6722
|
+
var CREDIT_ACTION_LABELS = {
|
|
6723
|
+
"mail.send_outbound": "外部出站邮件",
|
|
6724
|
+
"collab.space_create": "创建独立协作空间",
|
|
6725
|
+
"collab.boost_tasks": "协作任务扩容(+20)",
|
|
6726
|
+
"collab.boost_members": "协作成员扩容(+5)"
|
|
6727
|
+
};
|
|
6728
|
+
function creditMovement(entry) {
|
|
6729
|
+
if (entry.grantedDelta === null && entry.topupDelta === null)
|
|
6730
|
+
return entry.delta;
|
|
6731
|
+
return (entry.grantedDelta ?? 0) + (entry.topupDelta ?? 0);
|
|
6732
|
+
}
|
|
6733
|
+
async function fetchCredits(credentials, limit, offset) {
|
|
6734
|
+
const res = await api2(credentials.apiBase, `/v1/me/credits?limit=${limit}&offset=${offset}`, { headers: authHeaders(credentials) });
|
|
6735
|
+
if (res.status !== 200) {
|
|
6736
|
+
console.error(errorMessage(res.body, "获取积分数据失败。"));
|
|
6737
|
+
if (res.body?.error?.code === "scope_denied") {
|
|
6738
|
+
console.error("提示:积分命令需要 credits.read scope——运行 crab login --scopes account 重新授权。");
|
|
6739
|
+
}
|
|
6740
|
+
return exitCodeForApiError(res.body);
|
|
6741
|
+
}
|
|
6742
|
+
return res.body.data;
|
|
6743
|
+
}
|
|
6744
|
+
async function creditsBalance() {
|
|
6745
|
+
const credentials = requireCredentials();
|
|
6746
|
+
if (typeof credentials === "number")
|
|
6747
|
+
return credentials;
|
|
6748
|
+
const data = await fetchCredits(credentials, 1, 0);
|
|
6749
|
+
if (typeof data === "number")
|
|
6750
|
+
return data;
|
|
6751
|
+
if (hasFlag("--json")) {
|
|
6752
|
+
console.log(JSON.stringify(data.balance, null, 2));
|
|
6753
|
+
return 0;
|
|
6754
|
+
}
|
|
6755
|
+
console.log(`积分余额:${fmtCredits(data.balance.balance)}`);
|
|
6756
|
+
console.log(` 月送 ${fmtCredits(data.balance.granted)}(每周期刷新清零) · 充值 ${fmtCredits(data.balance.topup)}(长期有效)`);
|
|
6757
|
+
return 0;
|
|
6758
|
+
}
|
|
6759
|
+
async function creditsHistory() {
|
|
6760
|
+
const credentials = requireCredentials();
|
|
6761
|
+
if (typeof credentials === "number")
|
|
6762
|
+
return credentials;
|
|
6763
|
+
const limit = Math.min(Math.max(Number.parseInt(readFlag("--limit") ?? "", 10) || 20, 1), 100);
|
|
6764
|
+
const offset = Math.max(Number.parseInt(readFlag("--offset") ?? "", 10) || 0, 0);
|
|
6765
|
+
const data = await fetchCredits(credentials, limit, offset);
|
|
6766
|
+
if (typeof data === "number")
|
|
6767
|
+
return data;
|
|
6768
|
+
if (hasFlag("--json")) {
|
|
6769
|
+
console.log(JSON.stringify(data, null, 2));
|
|
6770
|
+
return 0;
|
|
6771
|
+
}
|
|
6772
|
+
if (data.ledger.length === 0) {
|
|
6773
|
+
console.log("还没有积分流水。");
|
|
6774
|
+
return 0;
|
|
6775
|
+
}
|
|
6776
|
+
for (const entry of data.ledger) {
|
|
6777
|
+
const movement = creditMovement(entry);
|
|
6778
|
+
const signed = movement > 0 ? `+${fmtCredits(movement)}` : fmtCredits(movement);
|
|
6779
|
+
console.log(`${formatTime(entry.createdAt)} ${CREDIT_REASON_LABELS[entry.reason] ?? entry.reason} ${signed}`);
|
|
6780
|
+
}
|
|
6781
|
+
console.log(`
|
|
6782
|
+
共 ${fmtCredits(data.total)} 条(本页 ${data.ledger.length} 条,--offset 翻页)`);
|
|
6783
|
+
return 0;
|
|
6784
|
+
}
|
|
6785
|
+
async function creditsPricing() {
|
|
6786
|
+
const credentials = loadCredentials();
|
|
6787
|
+
const apiBase = credentials ? credentials.apiBase : process.env.CRAB_API ?? readFlag("--api") ?? DEFAULT_API;
|
|
6788
|
+
const res = await api2(apiBase, "/v1/pricing/standard");
|
|
6789
|
+
if (res.status !== 200) {
|
|
6790
|
+
console.error(errorMessage(res.body, "获取动作计价失败。"));
|
|
6791
|
+
return exitCodeForApiError(res.body);
|
|
6792
|
+
}
|
|
6793
|
+
const actions = res.body.data?.actions ?? [];
|
|
6794
|
+
if (hasFlag("--json")) {
|
|
6795
|
+
console.log(JSON.stringify(res.body.data, null, 2));
|
|
6796
|
+
return 0;
|
|
6797
|
+
}
|
|
6798
|
+
if (actions.length === 0) {
|
|
6799
|
+
console.log("暂无动作计价项。");
|
|
6800
|
+
return 0;
|
|
6801
|
+
}
|
|
6802
|
+
console.log("动作计价(credit_cents,100 = $1.00):");
|
|
6803
|
+
for (const item of actions) {
|
|
6804
|
+
const label = CREDIT_ACTION_LABELS[item.action] ?? item.action;
|
|
6805
|
+
console.log(` ${item.action.padEnd(24)} ${label} ${fmtCredits(item.creditCents)} 积分`);
|
|
6806
|
+
}
|
|
6807
|
+
return 0;
|
|
6808
|
+
}
|
|
6481
6809
|
async function tokensList() {
|
|
6482
6810
|
const credentials = requireCredentials();
|
|
6483
6811
|
if (typeof credentials === "number")
|
|
@@ -6752,7 +7080,7 @@ async function mailSend() {
|
|
|
6752
7080
|
if (attachmentIds.length > 0)
|
|
6753
7081
|
console.log(` 附件 ${attachmentIds.length} 个(云盘引用,不复制)`);
|
|
6754
7082
|
if (result.chargedCredits > 0)
|
|
6755
|
-
console.log(`
|
|
7083
|
+
console.log(` 消耗积分:${fmtCredits(result.chargedCredits)}`);
|
|
6756
7084
|
if (result.failedExternal > 0)
|
|
6757
7085
|
console.log(` ⚠ ${result.failedExternal} 个外部收件人发送失败,对应积分已退回`);
|
|
6758
7086
|
return 0;
|
|
@@ -7704,6 +8032,19 @@ switch (command) {
|
|
|
7704
8032
|
process.exit(await storageUnshare(args[2]));
|
|
7705
8033
|
console.error(sub ? `未知子命令:storage ${sub}
|
|
7706
8034
|
` : `缺少子命令:storage ls | upload | download | rename | tag | category | publish | unpublish | rm | restore | purge | quota | categories | mkcat | tags | share | shares | unshare
|
|
8035
|
+
`);
|
|
8036
|
+
console.log(usage);
|
|
8037
|
+
process.exit(EXIT_USAGE);
|
|
8038
|
+
}
|
|
8039
|
+
case "credits": {
|
|
8040
|
+
const sub = args[1];
|
|
8041
|
+
if (!sub || sub === "balance")
|
|
8042
|
+
process.exit(await creditsBalance());
|
|
8043
|
+
if (sub === "history")
|
|
8044
|
+
process.exit(await creditsHistory());
|
|
8045
|
+
if (sub === "pricing")
|
|
8046
|
+
process.exit(await creditsPricing());
|
|
8047
|
+
console.error(`未知子命令:credits ${sub}
|
|
7707
8048
|
`);
|
|
7708
8049
|
console.log(usage);
|
|
7709
8050
|
process.exit(EXIT_USAGE);
|
|
@@ -30,6 +30,9 @@ Crab Cloud 是用户的个人云底座:账号、订阅与积分是平台层,
|
|
|
30
30
|
|---|---|
|
|
31
31
|
| 看账号身份 / 订阅 / 积分 | `crab whoami` |
|
|
32
32
|
| 程序化读取身份 | `crab whoami --json` |
|
|
33
|
+
| 积分余额(月送/充值/合计) | `crab credits`(需 `credits.read`,脚本消费加 `--json`) |
|
|
34
|
+
| 积分流水(花了多少、花在哪) | `crab credits history [--limit N] [--offset N]`(变动 ±:消耗为负;`--json` 含 total) |
|
|
35
|
+
| 查动作计价(如发一封外域邮件扣多少) | `crab credits pricing`(公开端点,无需登录) |
|
|
33
36
|
| 列出已授权的 Agent 令牌 | `crab tokens list`(脚本消费加 `--json`) |
|
|
34
37
|
| 撤销某个令牌(高危,先确认) | `crab tokens revoke <id>` |
|
|
35
38
|
| 重新授权 / 调整 scope | `crab login --scopes mail`(组名整组授权;也可单 scope 如 `mail.read`。浏览器确认,你只发起) |
|
|
@@ -39,6 +42,10 @@ Crab Cloud 是用户的个人云底座:账号、订阅与积分是平台层,
|
|
|
39
42
|
| 我的邀请码、邀请链接与受邀名单 | `crab contacts invite [--reset]` / `crab contacts invitees` |
|
|
40
43
|
| 管理登录设备 / 会话、修改密码 | 网页个人中心(crabcloud.cc/account)——CLI 有意不开放 |
|
|
41
44
|
|
|
45
|
+
积分命令需 `credits.read` scope(`account` 组含它):退出码 4 报缺该 scope 时,
|
|
46
|
+
引导 `crab login --scopes account` 重新授权。积分额度一律以**积分数**表述
|
|
47
|
+
(100 积分 = $1.00,仅价格类口径用美元);充值/下单是 Web 会话能力,CLI/Agent
|
|
48
|
+
令牌不动账——用户要充值时引导网页账单页(crabcloud.cc/account/billing)。
|
|
42
49
|
拿不准令牌 id 时先 `crab tokens list` 核对;`revoke` 只接受列表里的 id。
|
|
43
50
|
|
|
44
51
|
## 机器可读输出
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crabcloud/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Crab Cloud CLI (crab)
|
|
5
|
+
"description": "Crab Cloud CLI (crab) \u2014 agent-first entry to your personal cloud, with skills bundled for Claude Code / Codex / ZCode.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"crab": "dist/crab.js"
|
|
8
8
|
},
|