@ghostystudio/cli 0.39.0 → 0.40.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 +5 -0
- package/dist/index.js +208 -71
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -83,6 +83,7 @@ ghosty conversations ls --user EMAIL [--since 30d] · conversations show <id> <c
|
|
|
83
83
|
ghosty turns stats [--since 14d] [--all] · push log --user EMAIL [--since 2d]
|
|
84
84
|
ghosty agents doctor --user EMAIL [agent] [--turns 8] · usage --images [--plan free] [--by user]
|
|
85
85
|
ghosty novedades ls|create|set|test|send|rm [--title] [--body] [--image FILE] [--link] [--to] [--publish] [--at]
|
|
86
|
+
ghosty sites ls [--house] · sites publish <file.html|folder> [--title] [--slug S] [--site <slug|id>] · sites slug <slug|id> <new-slug> # house sites on EasyBits
|
|
86
87
|
ghosty credentials ls|set|rm [provider] [--from-env VAR] # never as an argument
|
|
87
88
|
ghosty docs
|
|
88
89
|
|
|
@@ -99,6 +100,10 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
99
100
|
|
|
100
101
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
101
102
|
|
|
103
|
+
### Changes in 0.40.0
|
|
104
|
+
|
|
105
|
+
- `sites ls [--house]`: the sites your agents published (or, staff, Ghosty's house sites). `sites publish <file.html|folder> [--title] [--slug S] [--site <slug|id>]` (staff) publishes a house site on EasyBits — no owner, no expiry, no banner; `--site` updates one. `sites slug <slug|id> <new-slug>` (staff) changes a site's slug. Slug errors come with a code: `slug_invalid`, `slug_taken`, `slug_unsupported` (EasyBits doesn't accept a slug yet; nothing changes, exit 1).
|
|
106
|
+
|
|
102
107
|
### Changes in 0.39.0
|
|
103
108
|
|
|
104
109
|
- `spaces transfer <workspace> --to EMAIL [--keep-as admin|member|none] [--copy-keys]` (staff): hands a workspace to a new owner in one step. Its agents go with it and spend the new owner's key, so `--copy-keys` copies the ones they lack (the dry run lists what's missing); the previous owner keeps the role you pick, and the agents' boxes are recycled so the new owner shows up everywhere.
|
package/dist/index.js
CHANGED
|
@@ -95,7 +95,7 @@ var require_visit = __commonJS({
|
|
|
95
95
|
"use strict";
|
|
96
96
|
var identity = require_identity();
|
|
97
97
|
var BREAK = /* @__PURE__ */ Symbol("break visit");
|
|
98
|
-
var
|
|
98
|
+
var SKIP2 = /* @__PURE__ */ Symbol("skip children");
|
|
99
99
|
var REMOVE = /* @__PURE__ */ Symbol("remove node");
|
|
100
100
|
function visit(node, visitor) {
|
|
101
101
|
const visitor_ = initVisitor(visitor);
|
|
@@ -107,7 +107,7 @@ var require_visit = __commonJS({
|
|
|
107
107
|
visit_(null, node, visitor_, Object.freeze([]));
|
|
108
108
|
}
|
|
109
109
|
visit.BREAK = BREAK;
|
|
110
|
-
visit.SKIP =
|
|
110
|
+
visit.SKIP = SKIP2;
|
|
111
111
|
visit.REMOVE = REMOVE;
|
|
112
112
|
function visit_(key, node, visitor, path) {
|
|
113
113
|
const ctrl = callVisitor(key, node, visitor, path);
|
|
@@ -155,7 +155,7 @@ var require_visit = __commonJS({
|
|
|
155
155
|
await visitAsync_(null, node, visitor_, Object.freeze([]));
|
|
156
156
|
}
|
|
157
157
|
visitAsync.BREAK = BREAK;
|
|
158
|
-
visitAsync.SKIP =
|
|
158
|
+
visitAsync.SKIP = SKIP2;
|
|
159
159
|
visitAsync.REMOVE = REMOVE;
|
|
160
160
|
async function visitAsync_(key, node, visitor, path) {
|
|
161
161
|
const ctrl = await callVisitor(key, node, visitor, path);
|
|
@@ -3122,9 +3122,9 @@ var require_timestamp = __commonJS({
|
|
|
3122
3122
|
const match = str.match(timestamp.test);
|
|
3123
3123
|
if (!match)
|
|
3124
3124
|
throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
3125
|
-
const [, year, month,
|
|
3125
|
+
const [, year, month, day2, hour, minute, second] = match.map(Number);
|
|
3126
3126
|
const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
|
|
3127
|
-
let date = Date.UTC(year, month - 1,
|
|
3127
|
+
let date = Date.UTC(year, month - 1, day2, hour || 0, minute || 0, second || 0, millisec);
|
|
3128
3128
|
const tz = match[8];
|
|
3129
3129
|
if (tz && tz !== "Z") {
|
|
3130
3130
|
let d = parseSexagesimal(tz, false);
|
|
@@ -3995,10 +3995,10 @@ var require_resolve_block_map = __commonJS({
|
|
|
3995
3995
|
let offset = bm.offset;
|
|
3996
3996
|
let commentEnd = null;
|
|
3997
3997
|
for (const collItem of bm.items) {
|
|
3998
|
-
const { start, key, sep, value } = collItem;
|
|
3998
|
+
const { start, key, sep: sep2, value } = collItem;
|
|
3999
3999
|
const keyProps = resolveProps.resolveProps(start, {
|
|
4000
4000
|
indicator: "explicit-key-ind",
|
|
4001
|
-
next: key ??
|
|
4001
|
+
next: key ?? sep2?.[0],
|
|
4002
4002
|
offset,
|
|
4003
4003
|
onError,
|
|
4004
4004
|
parentIndent: bm.indent,
|
|
@@ -4012,7 +4012,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4012
4012
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
4013
4013
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
4014
4014
|
}
|
|
4015
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
4015
|
+
if (!keyProps.anchor && !keyProps.tag && !sep2) {
|
|
4016
4016
|
commentEnd = keyProps.end;
|
|
4017
4017
|
if (keyProps.comment) {
|
|
4018
4018
|
if (map.comment)
|
|
@@ -4036,7 +4036,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4036
4036
|
ctx.atKey = false;
|
|
4037
4037
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
4038
4038
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
4039
|
-
const valueProps = resolveProps.resolveProps(
|
|
4039
|
+
const valueProps = resolveProps.resolveProps(sep2 ?? [], {
|
|
4040
4040
|
indicator: "map-value-ind",
|
|
4041
4041
|
next: value,
|
|
4042
4042
|
offset: keyNode.range[2],
|
|
@@ -4052,7 +4052,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4052
4052
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
4053
4053
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
4054
4054
|
}
|
|
4055
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
4055
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep2, null, valueProps, onError);
|
|
4056
4056
|
if (ctx.schema.compat)
|
|
4057
4057
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
4058
4058
|
offset = valueNode.range[2];
|
|
@@ -4143,7 +4143,7 @@ var require_resolve_end = __commonJS({
|
|
|
4143
4143
|
let comment = "";
|
|
4144
4144
|
if (end) {
|
|
4145
4145
|
let hasSpace = false;
|
|
4146
|
-
let
|
|
4146
|
+
let sep2 = "";
|
|
4147
4147
|
for (const token of end) {
|
|
4148
4148
|
const { source, type } = token;
|
|
4149
4149
|
switch (type) {
|
|
@@ -4157,13 +4157,13 @@ var require_resolve_end = __commonJS({
|
|
|
4157
4157
|
if (!comment)
|
|
4158
4158
|
comment = cb;
|
|
4159
4159
|
else
|
|
4160
|
-
comment +=
|
|
4161
|
-
|
|
4160
|
+
comment += sep2 + cb;
|
|
4161
|
+
sep2 = "";
|
|
4162
4162
|
break;
|
|
4163
4163
|
}
|
|
4164
4164
|
case "newline":
|
|
4165
4165
|
if (comment)
|
|
4166
|
-
|
|
4166
|
+
sep2 += source;
|
|
4167
4167
|
hasSpace = true;
|
|
4168
4168
|
break;
|
|
4169
4169
|
default:
|
|
@@ -4206,18 +4206,18 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4206
4206
|
let offset = fc.offset + fc.start.source.length;
|
|
4207
4207
|
for (let i = 0; i < fc.items.length; ++i) {
|
|
4208
4208
|
const collItem = fc.items[i];
|
|
4209
|
-
const { start, key, sep, value } = collItem;
|
|
4209
|
+
const { start, key, sep: sep2, value } = collItem;
|
|
4210
4210
|
const props = resolveProps.resolveProps(start, {
|
|
4211
4211
|
flow: fcName,
|
|
4212
4212
|
indicator: "explicit-key-ind",
|
|
4213
|
-
next: key ??
|
|
4213
|
+
next: key ?? sep2?.[0],
|
|
4214
4214
|
offset,
|
|
4215
4215
|
onError,
|
|
4216
4216
|
parentIndent: fc.indent,
|
|
4217
4217
|
startOnNewline: false
|
|
4218
4218
|
});
|
|
4219
4219
|
if (!props.found) {
|
|
4220
|
-
if (!props.anchor && !props.tag && !
|
|
4220
|
+
if (!props.anchor && !props.tag && !sep2 && !value) {
|
|
4221
4221
|
if (i === 0 && props.comma)
|
|
4222
4222
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
4223
4223
|
else if (i < fc.items.length - 1)
|
|
@@ -4271,8 +4271,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4271
4271
|
}
|
|
4272
4272
|
}
|
|
4273
4273
|
}
|
|
4274
|
-
if (!isMap && !
|
|
4275
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
4274
|
+
if (!isMap && !sep2 && !props.found) {
|
|
4275
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep2, null, props, onError);
|
|
4276
4276
|
coll.items.push(valueNode);
|
|
4277
4277
|
offset = valueNode.range[2];
|
|
4278
4278
|
if (isBlock(value))
|
|
@@ -4284,7 +4284,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4284
4284
|
if (isBlock(key))
|
|
4285
4285
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
4286
4286
|
ctx.atKey = false;
|
|
4287
|
-
const valueProps = resolveProps.resolveProps(
|
|
4287
|
+
const valueProps = resolveProps.resolveProps(sep2 ?? [], {
|
|
4288
4288
|
flow: fcName,
|
|
4289
4289
|
indicator: "map-value-ind",
|
|
4290
4290
|
next: value,
|
|
@@ -4295,8 +4295,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4295
4295
|
});
|
|
4296
4296
|
if (valueProps.found) {
|
|
4297
4297
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
4298
|
-
if (
|
|
4299
|
-
for (const st of
|
|
4298
|
+
if (sep2)
|
|
4299
|
+
for (const st of sep2) {
|
|
4300
4300
|
if (st === valueProps.found)
|
|
4301
4301
|
break;
|
|
4302
4302
|
if (st.type === "newline") {
|
|
@@ -4313,7 +4313,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4313
4313
|
else
|
|
4314
4314
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
4315
4315
|
}
|
|
4316
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
4316
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep2, null, valueProps, onError) : null;
|
|
4317
4317
|
if (valueNode) {
|
|
4318
4318
|
if (isBlock(value))
|
|
4319
4319
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -4493,7 +4493,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4493
4493
|
chompStart = i + 1;
|
|
4494
4494
|
}
|
|
4495
4495
|
let value = "";
|
|
4496
|
-
let
|
|
4496
|
+
let sep2 = "";
|
|
4497
4497
|
let prevMoreIndented = false;
|
|
4498
4498
|
for (let i = 0; i < contentStart; ++i)
|
|
4499
4499
|
value += lines[i][0].slice(trimIndent) + "\n";
|
|
@@ -4510,24 +4510,24 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4510
4510
|
indent = "";
|
|
4511
4511
|
}
|
|
4512
4512
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
4513
|
-
value +=
|
|
4514
|
-
|
|
4513
|
+
value += sep2 + indent.slice(trimIndent) + content;
|
|
4514
|
+
sep2 = "\n";
|
|
4515
4515
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
4516
|
-
if (
|
|
4517
|
-
|
|
4518
|
-
else if (!prevMoreIndented &&
|
|
4519
|
-
|
|
4520
|
-
value +=
|
|
4521
|
-
|
|
4516
|
+
if (sep2 === " ")
|
|
4517
|
+
sep2 = "\n";
|
|
4518
|
+
else if (!prevMoreIndented && sep2 === "\n")
|
|
4519
|
+
sep2 = "\n\n";
|
|
4520
|
+
value += sep2 + indent.slice(trimIndent) + content;
|
|
4521
|
+
sep2 = "\n";
|
|
4522
4522
|
prevMoreIndented = true;
|
|
4523
4523
|
} else if (content === "") {
|
|
4524
|
-
if (
|
|
4524
|
+
if (sep2 === "\n")
|
|
4525
4525
|
value += "\n";
|
|
4526
4526
|
else
|
|
4527
|
-
|
|
4527
|
+
sep2 = "\n";
|
|
4528
4528
|
} else {
|
|
4529
|
-
value +=
|
|
4530
|
-
|
|
4529
|
+
value += sep2 + content;
|
|
4530
|
+
sep2 = " ";
|
|
4531
4531
|
prevMoreIndented = false;
|
|
4532
4532
|
}
|
|
4533
4533
|
}
|
|
@@ -4710,25 +4710,25 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
4710
4710
|
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
4711
4711
|
}
|
|
4712
4712
|
let res = match[1].replace(trimEnd, "");
|
|
4713
|
-
let
|
|
4713
|
+
let sep2 = " ";
|
|
4714
4714
|
let pos = line2.lastIndex;
|
|
4715
4715
|
while (match = line2.exec(source)) {
|
|
4716
4716
|
const lm = match[1].replace(trimBoth, "");
|
|
4717
4717
|
if (lm === "") {
|
|
4718
|
-
if (
|
|
4719
|
-
res +=
|
|
4718
|
+
if (sep2 === "\n")
|
|
4719
|
+
res += sep2;
|
|
4720
4720
|
else
|
|
4721
|
-
|
|
4721
|
+
sep2 = "\n";
|
|
4722
4722
|
} else {
|
|
4723
|
-
res +=
|
|
4724
|
-
|
|
4723
|
+
res += sep2 + lm;
|
|
4724
|
+
sep2 = " ";
|
|
4725
4725
|
}
|
|
4726
4726
|
pos = line2.lastIndex;
|
|
4727
4727
|
}
|
|
4728
4728
|
const last = /[ \t]*(.*)/sy;
|
|
4729
4729
|
last.lastIndex = pos;
|
|
4730
4730
|
match = last.exec(source);
|
|
4731
|
-
return res +
|
|
4731
|
+
return res + sep2 + (match?.[1] ?? "");
|
|
4732
4732
|
}
|
|
4733
4733
|
function doubleQuotedValue(source, onError) {
|
|
4734
4734
|
let res = "";
|
|
@@ -5538,14 +5538,14 @@ var require_cst_stringify = __commonJS({
|
|
|
5538
5538
|
}
|
|
5539
5539
|
}
|
|
5540
5540
|
}
|
|
5541
|
-
function stringifyItem({ start, key, sep, value }) {
|
|
5541
|
+
function stringifyItem({ start, key, sep: sep2, value }) {
|
|
5542
5542
|
let res = "";
|
|
5543
5543
|
for (const st of start)
|
|
5544
5544
|
res += st.source;
|
|
5545
5545
|
if (key)
|
|
5546
5546
|
res += stringifyToken(key);
|
|
5547
|
-
if (
|
|
5548
|
-
for (const st of
|
|
5547
|
+
if (sep2)
|
|
5548
|
+
for (const st of sep2)
|
|
5549
5549
|
res += st.source;
|
|
5550
5550
|
if (value)
|
|
5551
5551
|
res += stringifyToken(value);
|
|
@@ -5560,7 +5560,7 @@ var require_cst_visit = __commonJS({
|
|
|
5560
5560
|
"../../node_modules/yaml/dist/parse/cst-visit.js"(exports) {
|
|
5561
5561
|
"use strict";
|
|
5562
5562
|
var BREAK = /* @__PURE__ */ Symbol("break visit");
|
|
5563
|
-
var
|
|
5563
|
+
var SKIP2 = /* @__PURE__ */ Symbol("skip children");
|
|
5564
5564
|
var REMOVE = /* @__PURE__ */ Symbol("remove item");
|
|
5565
5565
|
function visit(cst, visitor) {
|
|
5566
5566
|
if ("type" in cst && cst.type === "document")
|
|
@@ -5568,7 +5568,7 @@ var require_cst_visit = __commonJS({
|
|
|
5568
5568
|
_visit(Object.freeze([]), cst, visitor);
|
|
5569
5569
|
}
|
|
5570
5570
|
visit.BREAK = BREAK;
|
|
5571
|
-
visit.SKIP =
|
|
5571
|
+
visit.SKIP = SKIP2;
|
|
5572
5572
|
visit.REMOVE = REMOVE;
|
|
5573
5573
|
visit.itemAtPath = (cst, path) => {
|
|
5574
5574
|
let item = cst;
|
|
@@ -6712,18 +6712,18 @@ var require_parser = __commonJS({
|
|
|
6712
6712
|
if (this.type === "map-value-ind") {
|
|
6713
6713
|
const prev = getPrevProps(this.peek(2));
|
|
6714
6714
|
const start = getFirstKeyStartProps(prev);
|
|
6715
|
-
let
|
|
6715
|
+
let sep2;
|
|
6716
6716
|
if (scalar.end) {
|
|
6717
|
-
|
|
6718
|
-
|
|
6717
|
+
sep2 = scalar.end;
|
|
6718
|
+
sep2.push(this.sourceToken);
|
|
6719
6719
|
delete scalar.end;
|
|
6720
6720
|
} else
|
|
6721
|
-
|
|
6721
|
+
sep2 = [this.sourceToken];
|
|
6722
6722
|
const map = {
|
|
6723
6723
|
type: "block-map",
|
|
6724
6724
|
offset: scalar.offset,
|
|
6725
6725
|
indent: scalar.indent,
|
|
6726
|
-
items: [{ start, key: scalar, sep }]
|
|
6726
|
+
items: [{ start, key: scalar, sep: sep2 }]
|
|
6727
6727
|
};
|
|
6728
6728
|
this.onKeyLine = true;
|
|
6729
6729
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -6876,15 +6876,15 @@ var require_parser = __commonJS({
|
|
|
6876
6876
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
6877
6877
|
const start2 = getFirstKeyStartProps(it.start);
|
|
6878
6878
|
const key = it.key;
|
|
6879
|
-
const
|
|
6880
|
-
|
|
6879
|
+
const sep2 = it.sep;
|
|
6880
|
+
sep2.push(this.sourceToken);
|
|
6881
6881
|
delete it.key;
|
|
6882
6882
|
delete it.sep;
|
|
6883
6883
|
this.stack.push({
|
|
6884
6884
|
type: "block-map",
|
|
6885
6885
|
offset: this.offset,
|
|
6886
6886
|
indent: this.indent,
|
|
6887
|
-
items: [{ start: start2, key, sep }]
|
|
6887
|
+
items: [{ start: start2, key, sep: sep2 }]
|
|
6888
6888
|
});
|
|
6889
6889
|
} else if (start.length > 0) {
|
|
6890
6890
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -7078,13 +7078,13 @@ var require_parser = __commonJS({
|
|
|
7078
7078
|
const prev = getPrevProps(parent);
|
|
7079
7079
|
const start = getFirstKeyStartProps(prev);
|
|
7080
7080
|
fixFlowSeqItems(fc);
|
|
7081
|
-
const
|
|
7082
|
-
|
|
7081
|
+
const sep2 = fc.end.splice(1, fc.end.length);
|
|
7082
|
+
sep2.push(this.sourceToken);
|
|
7083
7083
|
const map = {
|
|
7084
7084
|
type: "block-map",
|
|
7085
7085
|
offset: fc.offset,
|
|
7086
7086
|
indent: fc.indent,
|
|
7087
|
-
items: [{ start, key: fc, sep }]
|
|
7087
|
+
items: [{ start, key: fc, sep: sep2 }]
|
|
7088
7088
|
};
|
|
7089
7089
|
this.onKeyLine = true;
|
|
7090
7090
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -8088,6 +8088,29 @@ var SERVER_MESSAGES = [
|
|
|
8088
8088
|
["turnToken excede {} caracteres", "turnToken exceeds {} characters"],
|
|
8089
8089
|
["turnToken no puede llevar espacios", "turnToken can't contain whitespace"],
|
|
8090
8090
|
["turnToken requerido: los MCP de este agente usan ${turn.token}", "turnToken required: this agent's MCP servers use ${turn.token}"],
|
|
8091
|
+
// — Sitios de la casa (`ghosty sites`, 3-oct)
|
|
8092
|
+
["los sitios de la casa: s\xF3lo el staff de Ghosty", "house sites: Ghosty staff only"],
|
|
8093
|
+
["publicar sitios de la casa: s\xF3lo el staff de Ghosty", "publishing house sites: Ghosty staff only"],
|
|
8094
|
+
["cambiar el slug de un sitio: s\xF3lo el staff de Ghosty", "changing a site's slug: Ghosty staff only"],
|
|
8095
|
+
["scope acepta mine o house", "scope takes mine or house"],
|
|
8096
|
+
["falta html o files", "missing html or files"],
|
|
8097
|
+
["falta slug", "missing slug"],
|
|
8098
|
+
["EasyBits todav\xEDa no permite elegir ni cambiar el slug", "EasyBits doesn't allow choosing or changing the slug yet"],
|
|
8099
|
+
["el slug \xAB{}\xBB ya est\xE1 ocupado en EasyBits", "slug \xAB{}\xBB is already taken on EasyBits"],
|
|
8100
|
+
["el slug \xAB{}\xBB ya est\xE1 ocupado", "slug \xAB{}\xBB is already taken"],
|
|
8101
|
+
["EasyBits rechaz\xF3 el slug \xAB{}\xBB por inv\xE1lido", "EasyBits rejected slug \xAB{}\xBB as invalid"],
|
|
8102
|
+
["el slug \xAB{}\xBB est\xE1 reservado", "slug \xAB{}\xBB is reserved"],
|
|
8103
|
+
["el slug debe tener entre 3 y 60 caracteres", "the slug must be 3 to 60 characters"],
|
|
8104
|
+
["el slug s\xF3lo admite min\xFAsculas (a-z), n\xFAmeros y guiones", "the slug only allows lowercase letters (a-z), digits and hyphens"],
|
|
8105
|
+
["el slug no puede empezar ni terminar en guion", "the slug can't start or end with a hyphen"],
|
|
8106
|
+
["el slug no puede llevar dos guiones seguidos", "the slug can't have two hyphens in a row"],
|
|
8107
|
+
["no encontr\xE9 un sitio vivo \xAB{}\xBB; publica sin `site` para crear uno nuevo", "no live site \xAB{}\xBB; publish without `site` to create a new one"],
|
|
8108
|
+
["no encontr\xE9 un sitio vivo \xAB{}\xBB", "no live site \xAB{}\xBB"],
|
|
8109
|
+
["ese sitio no es de la casa (s\xF3lo se actualizan con `--site` los publicados como casa)", "that site isn't a house site (--site only updates sites published as house)"],
|
|
8110
|
+
["la publicaci\xF3n de sitios no est\xE1 disponible en este momento", "site publishing isn't available right now"],
|
|
8111
|
+
["no pude conectar con el servicio de sitios ({})", "couldn't reach the sites service ({})"],
|
|
8112
|
+
["no se pudo crear el sitio; int\xE9ntalo en un momento", "couldn't create the site; try again in a moment"],
|
|
8113
|
+
["no se pudo subir {}: {}", "couldn't upload {}: {}"],
|
|
8091
8114
|
// — Infra interna (casi nunca llega al CLI, pero por si acaso)
|
|
8092
8115
|
["SESSION_SECRET ausente en producci\xF3n \u2014 las cookies quedar\xEDan firmadas con un valor p\xFAblico. Inyectarlo con ./scripts/set_gs_secret.sh SESSION_SECRET (openssl rand -hex 32).", "SESSION_SECRET missing in production \u2014 cookies would be signed with a public value. Inject it with ./scripts/set_gs_secret.sh SESSION_SECRET (openssl rand -hex 32)."],
|
|
8093
8116
|
["sqld: fetch sin namespace", "sqld: fetch without namespace"],
|
|
@@ -8390,7 +8413,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
8390
8413
|
const req = httpsRequest(`${base}${path}`, {
|
|
8391
8414
|
method: "POST",
|
|
8392
8415
|
timeout: timeoutMs,
|
|
8393
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
8416
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.40.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
8394
8417
|
}, (res) => {
|
|
8395
8418
|
let buf = "";
|
|
8396
8419
|
res.on("data", (c) => buf += c);
|
|
@@ -8432,7 +8455,7 @@ async function request(path, opts = {}, retried = false) {
|
|
|
8432
8455
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
8433
8456
|
headers: {
|
|
8434
8457
|
authorization: `Bearer ${token}`,
|
|
8435
|
-
"user-agent": `ghosty-cli/${"0.
|
|
8458
|
+
"user-agent": `ghosty-cli/${"0.40.0"}`,
|
|
8436
8459
|
"accept-language": lang(),
|
|
8437
8460
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
8438
8461
|
...opts.headers
|
|
@@ -8514,12 +8537,12 @@ var enc = encodeURIComponent;
|
|
|
8514
8537
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
8515
8538
|
var MIME = { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", gif: "image/gif", pdf: "application/pdf", ogg: "audio/ogg", opus: "audio/ogg", mp3: "audio/mpeg", m4a: "audio/mp4", wav: "audio/wav", mp4: "video/mp4" };
|
|
8516
8539
|
async function localFiles(paths) {
|
|
8517
|
-
const { readFile:
|
|
8518
|
-
const { basename:
|
|
8540
|
+
const { readFile: readFile15 } = await import("node:fs/promises");
|
|
8541
|
+
const { basename: basename5 } = await import("node:path");
|
|
8519
8542
|
return Promise.all(
|
|
8520
8543
|
paths.map(async (p) => {
|
|
8521
8544
|
const ext = p.toLowerCase().split(".").pop() ?? "";
|
|
8522
|
-
return { name:
|
|
8545
|
+
return { name: basename5(p), mimeType: MIME[ext] ?? "application/octet-stream", data: (await readFile15(p)).toString("base64") };
|
|
8523
8546
|
})
|
|
8524
8547
|
);
|
|
8525
8548
|
}
|
|
@@ -9618,7 +9641,7 @@ async function call(path, v, init = {}) {
|
|
|
9618
9641
|
"x-ghosty-ts": ts,
|
|
9619
9642
|
"x-ghosty-sig": sig,
|
|
9620
9643
|
"content-type": "application/json",
|
|
9621
|
-
"user-agent": `ghosty-cli/${"0.
|
|
9644
|
+
"user-agent": `ghosty-cli/${"0.40.0"}`
|
|
9622
9645
|
},
|
|
9623
9646
|
body: method === "GET" ? void 0 : raw
|
|
9624
9647
|
});
|
|
@@ -11272,6 +11295,16 @@ var HELPS_ES = {
|
|
|
11272
11295
|
summary: "Staff de Ghosty: las novedades de la app Android. Cada una con su ilustraci\xF3n; mismos frenos que el admin: pru\xE9bala en tu tel\xE9fono primero, push de 9 a 21 h CDMX, 72 h entre env\xEDos a todos.",
|
|
11273
11296
|
notes: ["ls dice, de una ya enviada, cu\xE1ntos entreg\xF3 y rechaz\xF3 FCM (del push log, desde el 1-oct).", "--image se publica en img.ghosty.studio (WebP 1200 px). --to vac\xEDo = todos. send sin --at la manda ya (pregunta); --at '' quita la programaci\xF3n.", "--min-version N (versionCode de Android): si la app del tester es m\xE1s vieja, el bot\xF3n dice \xABActualizar\xBB y lanza la actualizaci\xF3n de Play desde la app; '' la quita."]
|
|
11274
11297
|
},
|
|
11298
|
+
sites: {
|
|
11299
|
+
summary: "Sitios est\xE1ticos publicados en EasyBits con la cuenta de casa de Ghosty. ls lista los que publicaron tus agentes; el staff publica los artefactos de Ghosty (demos, landings) como sitios de la casa \u2014 sin due\xF1o, sin caducidad, sin la franja \xABHecha con Ghosty\xBB \u2014 y cambia el slug de cualquier sitio.",
|
|
11300
|
+
flags: [
|
|
11301
|
+
["--house", "ls (staff): los sitios de la casa en vez de los tuyos"],
|
|
11302
|
+
["--title T", "publish: el nombre del sitio (default: el <title> del HTML o el nombre de la carpeta)"],
|
|
11303
|
+
["--slug S", "publish: el slug de un sitio NUEVO (a-z, 0-9 y guiones, 3\u201360, no reservado)"],
|
|
11304
|
+
["--site X", "publish: actualiza ese sitio de la casa (slug, id o URL) en vez de crear uno"]
|
|
11305
|
+
],
|
|
11306
|
+
notes: ["Una carpeta necesita index.html en la ra\xEDz; se saltan ocultos y node_modules. Topes: 1 MB por archivo, 8 MB y 40 archivos por sitio.", "Sin --site, publish siempre crea un sitio nuevo (los de la casa nunca se buscan por t\xEDtulo).", "Errores de slug: slug_invalid, slug_taken, y slug_unsupported mientras EasyBits no acepte slug (exit 1, no cambia nada)."]
|
|
11307
|
+
},
|
|
11275
11308
|
spaces: {
|
|
11276
11309
|
summary: "Espacios: crea uno a tu nombre (prueba), lista los tuyos (o, staff, los de cualquiera) y operaciones del staff de Ghosty \u2014 entrar/salir del espacio de un cliente, cambiar su combo, mover \xABpagado hasta\xBB, renombrar su slug, cambiar de due\xF1o. Cada cambio queda en la bit\xE1cora del espacio.",
|
|
11277
11310
|
flags: [
|
|
@@ -11871,6 +11904,19 @@ HELPS.spaces = {
|
|
|
11871
11904
|
learn: `${REF}#espacios`
|
|
11872
11905
|
};
|
|
11873
11906
|
HELPS.workspaces = HELPS.spaces;
|
|
11907
|
+
HELPS.sites = {
|
|
11908
|
+
summary: "Static sites published on EasyBits with Ghosty's house account. ls lists the ones your agents published; staff publish Ghosty's own artifacts (demos, landings) as house sites \u2014 no owner, no expiry, no \xABMade with Ghosty\xBB banner \u2014 and change any site's slug.",
|
|
11909
|
+
usage: ["ghosty sites ls [--house]", "ghosty sites publish <file.html|folder> [--title T] [--slug S] [--site <slug|id>]", "ghosty sites slug <slug|id> <new-slug>"],
|
|
11910
|
+
flags: [
|
|
11911
|
+
["--house", "ls (staff): Ghosty's house sites instead of yours"],
|
|
11912
|
+
["--title T", "publish: the site's name (default: the HTML <title> or the folder name)"],
|
|
11913
|
+
["--slug S", "publish: the slug for a NEW site (a-z, 0-9 and hyphens, 3\u201360, not reserved)"],
|
|
11914
|
+
["--site X", "publish: update that house site (slug, id or URL) instead of creating one"]
|
|
11915
|
+
],
|
|
11916
|
+
examples: ["ghosty sites ls --house", 'ghosty sites publish ./melon.html --title "Gelatina de sand\xEDa" --slug gelatina-de-sandia', "ghosty sites publish ./landing/ --site gelatina-de-sandia", "ghosty sites slug arbol-palpitante gelatina-de-sandia"],
|
|
11917
|
+
notes: ["A folder needs index.html at its root; hidden files and node_modules are skipped. Limits: 1 MB per file, 8 MB and 40 files per site.", "Without --site, publish always creates a new site (house sites are never matched by title).", "Slug errors: slug_invalid, slug_taken, and slug_unsupported while EasyBits does not accept a slug yet (exit 1, nothing changes)."],
|
|
11918
|
+
learn: `${REF}#sitios`
|
|
11919
|
+
};
|
|
11874
11920
|
function helpText(cmd) {
|
|
11875
11921
|
const base = HELPS[cmd];
|
|
11876
11922
|
if (!base) return void 0;
|
|
@@ -12476,7 +12522,7 @@ ${dim(t(`${total2} message(s) unanswered for lack of balance in ${r.days} day(s)
|
|
|
12476
12522
|
d.noQuota += x.noQuota;
|
|
12477
12523
|
days.set(x.day, d);
|
|
12478
12524
|
}
|
|
12479
|
-
rows = [...days].map(([
|
|
12525
|
+
rows = [...days].map(([day2, x]) => ({ day: day2, ...fmt2(x) }));
|
|
12480
12526
|
} else rows = r.agents.map((x) => ({ agent: x.agent, ...fmt2(x) }));
|
|
12481
12527
|
const cols = [...by.has("day") ? ["day"] : [], ...by.has("agent") ? ["agent"] : [], "turns", "failed", "tokens", "no balance"];
|
|
12482
12528
|
const total = r.agents.reduce((n, a) => n + a.billable, 0);
|
|
@@ -12601,8 +12647,84 @@ async function demosCmd(sub, a1, rest, v) {
|
|
|
12601
12647
|
throw usage(t(`Unknown demos subcommand: ${sub ?? "(none)"}.`, `Subcomando de demos desconocido: ${sub ?? "(ninguno)"}.`), 'ghosty demos history <agent> \xB7 ghosty demos try <slug> "message"');
|
|
12602
12648
|
}
|
|
12603
12649
|
|
|
12650
|
+
// src/commands/sites.ts
|
|
12651
|
+
import { readdir as readdir5, readFile as readFile13, stat as stat2 } from "node:fs/promises";
|
|
12652
|
+
import { basename as basename4, join as join10, relative as relative2, sep } from "node:path";
|
|
12653
|
+
var TEXT_EXT = /* @__PURE__ */ new Set(["html", "htm", "css", "js", "mjs", "json", "txt", "xml", "svg", "webmanifest", "md"]);
|
|
12654
|
+
var SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", ".DS_Store"]);
|
|
12655
|
+
async function collectSiteFiles(target) {
|
|
12656
|
+
const st = await stat2(target).catch(() => null);
|
|
12657
|
+
if (!st) throw usage(t(`Not found: ${target}`, `No existe: ${target}`));
|
|
12658
|
+
if (st.isFile()) {
|
|
12659
|
+
if (!/\.html?$/i.test(target)) throw usage(t("A single file must be .html (or pass a folder).", "Un archivo suelto debe ser .html (o pasa una carpeta)."));
|
|
12660
|
+
const html = await readFile13(target, "utf8");
|
|
12661
|
+
return { files: [{ path: "index.html", content: html, encoding: "text" }], title: titleOf(html) };
|
|
12662
|
+
}
|
|
12663
|
+
const files = [];
|
|
12664
|
+
const walk = async (dir) => {
|
|
12665
|
+
for (const e of await readdir5(dir, { withFileTypes: true })) {
|
|
12666
|
+
if (e.name.startsWith(".") || SKIP.has(e.name)) continue;
|
|
12667
|
+
const full = join10(dir, e.name);
|
|
12668
|
+
if (e.isDirectory()) await walk(full);
|
|
12669
|
+
else if (e.isFile()) {
|
|
12670
|
+
const path = relative2(target, full).split(sep).join("/");
|
|
12671
|
+
const ext = path.split(".").pop()?.toLowerCase() ?? "";
|
|
12672
|
+
const buf = await readFile13(full);
|
|
12673
|
+
files.push(TEXT_EXT.has(ext) ? { path, content: buf.toString("utf8"), encoding: "text" } : { path, content: buf.toString("base64"), encoding: "base64" });
|
|
12674
|
+
}
|
|
12675
|
+
}
|
|
12676
|
+
};
|
|
12677
|
+
await walk(target);
|
|
12678
|
+
const index = files.find((f) => f.path === "index.html");
|
|
12679
|
+
if (!index) throw usage(t(`${target} has no index.html at its root.`, `${target} no tiene index.html en la ra\xEDz.`));
|
|
12680
|
+
return { files: files.sort((a, b) => a.path.localeCompare(b.path)), title: titleOf(index.content) ?? basename4(target.replace(/\/+$/, "")) };
|
|
12681
|
+
}
|
|
12682
|
+
function titleOf(html) {
|
|
12683
|
+
const m = html.match(/<title[^>]*>([^<]*)<\/title>/i);
|
|
12684
|
+
const s = m?.[1]?.replace(/\s+/g, " ").trim();
|
|
12685
|
+
return s || null;
|
|
12686
|
+
}
|
|
12687
|
+
var kb = (n) => n ? `${Math.max(1, Math.round(n / 1024))} KB` : "";
|
|
12688
|
+
var day = (iso) => iso ? iso.slice(0, 10) : "";
|
|
12689
|
+
async function sitesCmd(sub, a1, a2, v) {
|
|
12690
|
+
const ex = "ghosty sites publish <file.html|folder> [--title T] [--slug S] [--site <slug|id>] \xB7 ls [--house] \xB7 slug <slug|id> <new-slug>";
|
|
12691
|
+
switch (sub ?? "ls") {
|
|
12692
|
+
case "ls":
|
|
12693
|
+
case "list": {
|
|
12694
|
+
const r = await api(`/api/v2/sites?scope=${v.house ? "house" : "mine"}`);
|
|
12695
|
+
const rows = r.sites.map((s) => ({ slug: s.slug, title: (s.title ?? "").slice(0, 40), url: s.url, files: s.files ?? "", size: kb(s.bytes), published: day(s.publishedAt), expires: s.expiresAt ? day(s.expiresAt) : t("never", "nunca") }));
|
|
12696
|
+
return out(r, () => `${bold(v.house ? t("House sites", "Sitios de la casa") : t("Your sites", "Tus sitios"))}
|
|
12697
|
+
${table(rows, ["slug", "title", "url", "files", "size", "published", "expires"])}`);
|
|
12698
|
+
}
|
|
12699
|
+
case "publish":
|
|
12700
|
+
case "deploy": {
|
|
12701
|
+
if (!a1) throw usage(t("Missing the file or folder.", "Falta el archivo o la carpeta."), ex);
|
|
12702
|
+
const { files, title } = await collectSiteFiles(a1);
|
|
12703
|
+
const body = {
|
|
12704
|
+
title: v.title ?? title ?? "Sitio de Ghosty",
|
|
12705
|
+
...files.length === 1 && files[0].path === "index.html" && files[0].encoding === "text" ? { html: files[0].content } : { files },
|
|
12706
|
+
...v.site ? { site: v.site } : {},
|
|
12707
|
+
...v.slug ? { slug: v.slug } : {}
|
|
12708
|
+
};
|
|
12709
|
+
const r = await api("/api/v2/sites", { method: "POST", body });
|
|
12710
|
+
return out(r, () => `${lavender("\u2713")} ${r.created ? t("Published", "Publicado") : t("Updated", "Actualizado")} ${bold(r.url)}
|
|
12711
|
+
${dim(t(`slug ${r.slug} \xB7 ${files.length} file(s) \xB7 update it: ghosty sites publish ${a1} --site ${r.slug}`, `slug ${r.slug} \xB7 ${files.length} archivo(s) \xB7 actual\xEDzalo: ghosty sites publish ${a1} --site ${r.slug}`))}`);
|
|
12712
|
+
}
|
|
12713
|
+
case "slug":
|
|
12714
|
+
case "rename": {
|
|
12715
|
+
if (!a1 || !a2) throw usage(t("Missing the site and the new slug.", "Faltan el sitio y el slug nuevo."), "ghosty sites slug <slug|id> <new-slug>");
|
|
12716
|
+
const r = await api(`/api/v2/sites/${encodeURIComponent(a1)}`, { method: "PATCH", body: { slug: a2 } });
|
|
12717
|
+
return out(r, () => `${lavender("\u2713")} ${r.oldSlug} \u2192 ${bold(r.slug)}
|
|
12718
|
+
${r.url}
|
|
12719
|
+
${dim(t("Links with the old slug may stop working.", "Las ligas con el slug viejo pueden dejar de funcionar."))}`);
|
|
12720
|
+
}
|
|
12721
|
+
default:
|
|
12722
|
+
throw usage(t(`Unknown sites subcommand: ${sub}.`, `Subcomando de sites desconocido: ${sub}.`), ex);
|
|
12723
|
+
}
|
|
12724
|
+
}
|
|
12725
|
+
|
|
12604
12726
|
// src/commands/support.ts
|
|
12605
|
-
import { readFile as
|
|
12727
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
12606
12728
|
var enc12 = encodeURIComponent;
|
|
12607
12729
|
var cdmx = (iso) => new Date(Date.parse(iso) - 6 * 36e5).toISOString().slice(5, 16).replace("T", " ");
|
|
12608
12730
|
async function supportThreads(email, v) {
|
|
@@ -12712,7 +12834,7 @@ async function novedadesCmd(sub, id, v) {
|
|
|
12712
12834
|
const fields = async () => ({
|
|
12713
12835
|
...v.title !== void 0 ? { title: v.title } : {},
|
|
12714
12836
|
...v.body !== void 0 ? { body: v.body } : {},
|
|
12715
|
-
...v.image ? { image: (await
|
|
12837
|
+
...v.image ? { image: (await readFile14(v.image)).toString("base64") } : {},
|
|
12716
12838
|
...v.link !== void 0 ? { enlace: v.link || null } : {},
|
|
12717
12839
|
...v.button !== void 0 ? { boton: v.button || null } : {},
|
|
12718
12840
|
...v.to !== void 0 ? { destinatarios: v.to || null } : {},
|
|
@@ -12904,6 +13026,11 @@ ${bold("Support")} ${dim("(Ghosty staff)")}
|
|
|
12904
13026
|
push log --user EMAIL Pushes sent to someone and what Apple/Google answered [--since 2d]
|
|
12905
13027
|
novedades ls|create|set|test|send|rm Android app announcements [--title] [--body] [--image FILE] [--link] [--to] [--min-version N] [--publish] [--at]
|
|
12906
13028
|
|
|
13029
|
+
${bold("Sites")} ${dim("(static sites on EasyBits with Ghosty's house account)")}
|
|
13030
|
+
sites ls Sites your agents published [--house: Ghosty's own demos and landings (staff)]
|
|
13031
|
+
sites publish <file.html|folder> Publish a house site (staff): no owner, no expiry, no banner [--title] [--slug S] [--site <slug|id>: update that one]
|
|
13032
|
+
sites slug <slug|id> <new-slug> Change a site's slug (staff)
|
|
13033
|
+
|
|
12907
13034
|
${bold("Demos")}
|
|
12908
13035
|
demos try <slug> "msg" ["msg2"\u2026] Try a public demo as a visitor (same thread across runs) [--new] [--recycle-between --agent X]
|
|
12909
13036
|
demos history <id> What visitors did: turns, messages, files (Ghosty staff) [--since 2d] [--session web:\u2026] [--timeline] [--full]
|
|
@@ -13034,6 +13161,11 @@ ${bold("Soporte")} ${dim("(staff de Ghosty)")}
|
|
|
13034
13161
|
push log --user CORREO Avisos que se le mandaron a alguien y qu\xE9 contest\xF3 Apple/Google [--since 2d]
|
|
13035
13162
|
novedades ls|create|set|test|send|rm Novedades de la app Android [--title] [--body] [--image ARCHIVO] [--link] [--to] [--min-version N] [--publish] [--at]
|
|
13036
13163
|
|
|
13164
|
+
${bold("Sitios")} ${dim("(sitios est\xE1ticos en EasyBits con la cuenta de casa de Ghosty)")}
|
|
13165
|
+
sites ls Sitios que publicaron tus agentes [--house: demos y landings de Ghosty (staff)]
|
|
13166
|
+
sites publish <archivo.html|carpeta> Publica un sitio de la casa (staff): sin due\xF1o, sin caducidad, sin franja [--title] [--slug S] [--site <slug|id>: actualiza \xE9se]
|
|
13167
|
+
sites slug <slug|id> <slug-nuevo> Cambia el slug de un sitio (staff)
|
|
13168
|
+
|
|
13037
13169
|
${bold("Demos")}
|
|
13038
13170
|
demos try <slug> "msg" ["msg2"\u2026] Prueba un demo p\xFAblico como visitante (mismo hilo entre corridas) [--new] [--recycle-between --agent X]
|
|
13039
13171
|
demos history <id> Qu\xE9 hicieron los visitantes: turnos, mensajes, archivos (staff de Ghosty) [--since 2d] [--session web:\u2026] [--timeline] [--full]
|
|
@@ -13079,7 +13211,7 @@ ${bold("Opciones globales")}
|
|
|
13079
13211
|
${bold("C\xF3digos de salida")} 0 bien \xB7 1 error de la API \xB7 2 uso incorrecto \xB7 3 sin sesi\xF3n
|
|
13080
13212
|
${dim("Nota: `ghosty` puede chocar con otro binario en tu PATH (p. ej. la TUI de Ghosty). Rev\xEDsalo con `which -a ghosty`; corre `npx @ghostystudio/cli` para ir a la segura.")}
|
|
13081
13213
|
${dim("Documentaci\xF3n: https://www.ghosty.studio/docs/cli")}`;
|
|
13082
|
-
var COMMANDS = ["login", "logout", "whoami", "usage", "use", "apply", "plan", "engines", "bags", "spaces", "workspaces", "demos", "push", "novedades", "completion", "cards", "agents", "files", "skills", "mcp", "dbs", "turns", "try", "chat", "conversations", "schedule", "partner", "me", "channels", "board", "boards", "credentials", "docs", "help"];
|
|
13214
|
+
var COMMANDS = ["login", "logout", "whoami", "usage", "use", "apply", "plan", "engines", "bags", "spaces", "workspaces", "demos", "sites", "push", "novedades", "completion", "cards", "agents", "files", "skills", "mcp", "dbs", "turns", "try", "chat", "conversations", "schedule", "partner", "me", "channels", "board", "boards", "credentials", "docs", "help"];
|
|
13083
13215
|
var AGENTS_SUBS = ["ls", "create", "get", "set", "export", "doctor", "docs", "share", "unshare", "shares", "rm", "restart", "demo", "box"];
|
|
13084
13216
|
function unknown(what, input, known, helpCmd) {
|
|
13085
13217
|
const s = suggest(input, known);
|
|
@@ -13155,6 +13287,8 @@ async function main() {
|
|
|
13155
13287
|
config: { type: "string" },
|
|
13156
13288
|
"turn-token": { type: "string" },
|
|
13157
13289
|
slug: { type: "string" },
|
|
13290
|
+
site: { type: "string" },
|
|
13291
|
+
house: { type: "boolean" },
|
|
13158
13292
|
on: { type: "boolean" },
|
|
13159
13293
|
off: { type: "boolean" },
|
|
13160
13294
|
turns: { type: "string" },
|
|
@@ -13302,7 +13436,7 @@ async function main() {
|
|
|
13302
13436
|
const tokens = splitTokens(pos, v);
|
|
13303
13437
|
globals.token = tokens.session;
|
|
13304
13438
|
globals.profile = v.profile;
|
|
13305
|
-
if (v.version) return out({ version: "0.
|
|
13439
|
+
if (v.version) return out({ version: "0.40.0" }, () => "0.40.0");
|
|
13306
13440
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
13307
13441
|
const context = (await readConfig()).workspace;
|
|
13308
13442
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -13391,6 +13525,9 @@ async function main() {
|
|
|
13391
13525
|
case "novedades":
|
|
13392
13526
|
case "announcements":
|
|
13393
13527
|
return novedadesCmd(sub, a1, v);
|
|
13528
|
+
case "sites":
|
|
13529
|
+
case "site":
|
|
13530
|
+
return sitesCmd(sub, a1, a2, v);
|
|
13394
13531
|
case "board":
|
|
13395
13532
|
return boardCmd(sub, a1, v, a2);
|
|
13396
13533
|
case "boards":
|
|
@@ -13451,7 +13588,7 @@ async function main() {
|
|
|
13451
13588
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
13452
13589
|
}
|
|
13453
13590
|
}
|
|
13454
|
-
var notice = updateNotice("0.
|
|
13591
|
+
var notice = updateNotice("0.40.0").catch(() => null);
|
|
13455
13592
|
main().then(
|
|
13456
13593
|
async () => {
|
|
13457
13594
|
const n = await notice;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghostystudio/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "Official Ghosty Studio CLI — configure, test and chat with your agents from the terminal. Built for humans and coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --outfile=dist/index.js --banner:js='#!/usr/bin/env node\nimport { createRequire as __cr } from \"node:module\"; const require = __cr(import.meta.url);' --define:__VERSION__=\\\"$npm_package_version\\\"",
|
|
18
18
|
"prepack": "npm run build",
|
|
19
|
-
"test": "for t in flags prompt api rows wa-auth resolve aliases i18n help completion photos channels-retry spaces; do esbuild src/$t.test.ts --bundle --platform=node --format=esm --outfile=/tmp/ghosty-cli-$t.test.mjs --log-level=error || exit 1; done && node --test /tmp/ghosty-cli-*.test.mjs"
|
|
19
|
+
"test": "for t in flags prompt api rows wa-auth resolve aliases i18n help completion photos channels-retry spaces sites; do esbuild src/$t.test.ts --bundle --platform=node --format=esm --outfile=/tmp/ghosty-cli-$t.test.mjs --log-level=error || exit 1; done && node --test /tmp/ghosty-cli-*.test.mjs"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"ghosty",
|