gamesteel 0.5.2 → 0.5.3
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/gamesteel.js +301 -16
- package/dist/pkgs/studio/dist/server/playtest-worker.js +67 -10
- package/package.json +11 -11
package/dist/gamesteel.js
CHANGED
|
@@ -86206,6 +86206,7 @@ var PLANS = [
|
|
|
86206
86206
|
monthly: 999,
|
|
86207
86207
|
seats: 1,
|
|
86208
86208
|
extraSeat: null,
|
|
86209
|
+
storageBlock: 499,
|
|
86209
86210
|
everythingIn: null,
|
|
86210
86211
|
pick: false,
|
|
86211
86212
|
storage: 10 * GB,
|
|
@@ -86213,7 +86214,7 @@ var PLANS = [
|
|
|
86213
86214
|
includes: [
|
|
86214
86215
|
room(10 * GB, 500 * MB),
|
|
86215
86216
|
line("Everything Gamesteel does, with your own agent"),
|
|
86216
|
-
line("The agent's
|
|
86217
|
+
line("The agent's 16 tools"),
|
|
86217
86218
|
line("Export to the web"),
|
|
86218
86219
|
line("Phone app builds")
|
|
86219
86220
|
]
|
|
@@ -86224,6 +86225,7 @@ var PLANS = [
|
|
|
86224
86225
|
monthly: 1999,
|
|
86225
86226
|
seats: 3,
|
|
86226
86227
|
extraSeat: 1e3,
|
|
86228
|
+
storageBlock: 399,
|
|
86227
86229
|
everythingIn: "starter",
|
|
86228
86230
|
pick: true,
|
|
86229
86231
|
storage: 50 * GB,
|
|
@@ -86231,11 +86233,12 @@ var PLANS = [
|
|
|
86231
86233
|
includes: [room(50 * GB, GB), line("An organization with shared games and roles")]
|
|
86232
86234
|
},
|
|
86233
86235
|
{
|
|
86234
|
-
id: "
|
|
86235
|
-
name: "
|
|
86236
|
+
id: "business",
|
|
86237
|
+
name: "Business",
|
|
86236
86238
|
monthly: 3999,
|
|
86237
86239
|
seats: 20,
|
|
86238
|
-
extraSeat:
|
|
86240
|
+
extraSeat: 800,
|
|
86241
|
+
storageBlock: 299,
|
|
86239
86242
|
everythingIn: "pro",
|
|
86240
86243
|
pick: false,
|
|
86241
86244
|
storage: 250 * GB,
|
|
@@ -86243,6 +86246,12 @@ var PLANS = [
|
|
|
86243
86246
|
includes: [room(250 * GB, 2 * GB), line("Invoices instead of cards"), line("Priority support")]
|
|
86244
86247
|
}
|
|
86245
86248
|
];
|
|
86249
|
+
var ENTERPRISE = {
|
|
86250
|
+
name: "Enterprise",
|
|
86251
|
+
everythingIn: "business",
|
|
86252
|
+
includes: [line("Seats and storage sized for your team"), line("Terms and invoicing agreed with you"), line("A direct line to the team")],
|
|
86253
|
+
email: "business@gamesteel.studio"
|
|
86254
|
+
};
|
|
86246
86255
|
var TRIAL = {
|
|
86247
86256
|
days: 7,
|
|
86248
86257
|
games: 1,
|
|
@@ -86252,11 +86261,17 @@ var TRIAL = {
|
|
|
86252
86261
|
gameBytes: 200 * MB,
|
|
86253
86262
|
rules: ["One week, free", "One game", "No export", "A watermark on the game"]
|
|
86254
86263
|
};
|
|
86255
|
-
var STORAGE_BLOCK = { bytes: 10 * GB
|
|
86264
|
+
var STORAGE_BLOCK = { bytes: 10 * GB };
|
|
86256
86265
|
var STORAGE_FULL = (site, allowed) => `this workspace's ${sizeText(allowed)} are full: delete something it keeps, or its owner can add storage or choose a bigger plan at ${site}/editor#plan`;
|
|
86257
86266
|
var GAME_FULL = (site, allowed) => `a game may hold at most ${sizeText(allowed)} on this plan: delete something in it, or its owner can choose a bigger plan at ${site}/editor#plan`;
|
|
86258
86267
|
var NEARLY_FULL = 0.8;
|
|
86259
86268
|
var UNLIMITED_GAME_BYTES = 2 * GB;
|
|
86269
|
+
function planById(id) {
|
|
86270
|
+
const plan = PLANS.find((one2) => one2.id === id);
|
|
86271
|
+
if (plan === void 0)
|
|
86272
|
+
throw new Error(`no plan called ${id}`);
|
|
86273
|
+
return plan;
|
|
86274
|
+
}
|
|
86260
86275
|
|
|
86261
86276
|
// ../edit/dist/model.js
|
|
86262
86277
|
var TILE_LAYERS = ["back", "front"];
|
|
@@ -107276,7 +107291,8 @@ var NEEDS_PROGRAM6 = "exporting to a file runs in the Gamesteel program on your
|
|
|
107276
107291
|
var EXPORT_TOOLS = [
|
|
107277
107292
|
{
|
|
107278
107293
|
name: "export_game",
|
|
107279
|
-
|
|
107294
|
+
// Its words cut to make room under Cursor's list size for the website's own tool (2026-10-26).
|
|
107295
|
+
description: "write the game's export, a zip that plays anywhere, on this machine, and say where it is: unzipped, its index.html plays in a browser. A plan exports games up to its cap; a large game takes minutes, and memory.",
|
|
107280
107296
|
inputSchema: object2({ game: GAME }, ["game"]),
|
|
107281
107297
|
handle: async (args2, ctx) => {
|
|
107282
107298
|
const slug = textArg(args2, "game");
|
|
@@ -111289,7 +111305,7 @@ var DEFAULT_SERVE = { schemas: "full" };
|
|
|
111289
111305
|
var SINGLES2 = ["guide", "edit", "write_code", "team"];
|
|
111290
111306
|
var fam = (name2, about, actions) => ({ name: name2, about, actions: Object.entries(actions).map(([action, tool]) => ({ action, tool })) });
|
|
111291
111307
|
var FAMILIES2 = [
|
|
111292
|
-
fam("games", "the games in the library
|
|
111308
|
+
fam("games", "the games in the library, and game text given as source", {
|
|
111293
111309
|
list: "list_games",
|
|
111294
111310
|
open: "open_game",
|
|
111295
111311
|
new: "new_game",
|
|
@@ -111316,7 +111332,7 @@ var FAMILIES2 = [
|
|
|
111316
111332
|
redo: "redo",
|
|
111317
111333
|
art: "undo_art"
|
|
111318
111334
|
}),
|
|
111319
|
-
fam("playtest", "play the game yourself, headless
|
|
111335
|
+
fam("playtest", "play the game yourself, headless, and look at it", {
|
|
111320
111336
|
play: "playtest_play",
|
|
111321
111337
|
until: "playtest_until",
|
|
111322
111338
|
look: "playtest_look",
|
|
@@ -111325,13 +111341,13 @@ var FAMILIES2 = [
|
|
|
111325
111341
|
snapshot: "playtest_snapshot",
|
|
111326
111342
|
restore: "playtest_restore"
|
|
111327
111343
|
}),
|
|
111328
|
-
fam("art", "a game's pictures
|
|
111344
|
+
fam("art", "a game's pictures, painted or modelled in 3D", {
|
|
111329
111345
|
paint: "paint_art",
|
|
111330
111346
|
model: "model_art",
|
|
111331
111347
|
read: "read_art",
|
|
111332
111348
|
list: "list_art"
|
|
111333
111349
|
}),
|
|
111334
|
-
fam("sound", "a game's sound
|
|
111350
|
+
fam("sound", "a game's sound effects and music", {
|
|
111335
111351
|
design: "design_sound",
|
|
111336
111352
|
compose: "compose_music",
|
|
111337
111353
|
listen: "listen",
|
|
@@ -111357,6 +111373,14 @@ var FAMILIES2 = [
|
|
|
111357
111373
|
online: "app_online",
|
|
111358
111374
|
online_logs: "app_online_logs",
|
|
111359
111375
|
online_query: "app_online_query"
|
|
111376
|
+
}),
|
|
111377
|
+
// The 16th (the owner, 2026-10-26): what is the website's, not a game's.
|
|
111378
|
+
fam("website", "your Gamesteel account on the website", {
|
|
111379
|
+
account: "website_account",
|
|
111380
|
+
workspaces: "website_workspaces",
|
|
111381
|
+
members: "website_members",
|
|
111382
|
+
storage: "website_storage",
|
|
111383
|
+
sign_in: "sign_in"
|
|
111360
111384
|
})
|
|
111361
111385
|
];
|
|
111362
111386
|
function nowCalled(tool) {
|
|
@@ -111447,7 +111471,7 @@ function listingOf(family2, tools) {
|
|
|
111447
111471
|
};
|
|
111448
111472
|
for (const [key, { shape, uses }] of options)
|
|
111449
111473
|
properties[key] = { ...shape, description: saidOf(uses, present2.length) };
|
|
111450
|
-
const description = [`${family2.about}.
|
|
111474
|
+
const description = [`${family2.about}. Actions:`, ...present2.map((a4) => `- ${a4.action}: ${a4.def.description}`)].join("\n");
|
|
111451
111475
|
return { name: family2.name, description, inputSchema: { type: "object", additionalProperties: false, required: ["action"], properties } };
|
|
111452
111476
|
}
|
|
111453
111477
|
var ORDER = [
|
|
@@ -111465,7 +111489,8 @@ var ORDER = [
|
|
|
111465
111489
|
"library",
|
|
111466
111490
|
"film",
|
|
111467
111491
|
"team",
|
|
111468
|
-
"app"
|
|
111492
|
+
"app",
|
|
111493
|
+
"website"
|
|
111469
111494
|
];
|
|
111470
111495
|
function familyListing(tools) {
|
|
111471
111496
|
const singles = SINGLES2.flatMap((name2) => tools.filter((t2) => t2.name === name2));
|
|
@@ -111513,6 +111538,20 @@ var WAIT_TOOL = {
|
|
|
111513
111538
|
description: `wait up to ${String(JOB_MS / 1e3)} seconds for a call of yours still going, and answer with what it said`,
|
|
111514
111539
|
inputSchema: { type: "object", additionalProperties: false, properties: {} }
|
|
111515
111540
|
};
|
|
111541
|
+
var WEBSITE_READS = { account: "website_account", workspaces: "website_workspaces", members: "website_members", storage: "website_storage" };
|
|
111542
|
+
var NO_OPTIONS = { type: "object", additionalProperties: false, properties: {} };
|
|
111543
|
+
var WEBSITE_TOOLS = [
|
|
111544
|
+
{ name: WEBSITE_READS.account, description: "which account and workspace this works in, its plan, limits and pages", inputSchema: NO_OPTIONS },
|
|
111545
|
+
{ name: WEBSITE_READS.workspaces, description: "the person's workspaces, their role in each, and which this works in", inputSchema: NO_OPTIONS },
|
|
111546
|
+
{ name: WEBSITE_READS.members, description: "the workspace's people and their roles", inputSchema: NO_OPTIONS },
|
|
111547
|
+
{ name: WEBSITE_READS.storage, description: "what the workspace keeps: by kind, the largest files, what no game uses", inputSchema: NO_OPTIONS }
|
|
111548
|
+
];
|
|
111549
|
+
var WEBSITE_NAMES = new Set(Object.values(WEBSITE_READS));
|
|
111550
|
+
var SIGN_IN_TOOL = {
|
|
111551
|
+
name: "sign_in",
|
|
111552
|
+
description: "sign in again, as another account or workspace",
|
|
111553
|
+
inputSchema: { type: "object", additionalProperties: false, properties: {} }
|
|
111554
|
+
};
|
|
111516
111555
|
var NOTHING_GOING = "no call of yours is going on";
|
|
111517
111556
|
function guideAnswer(raw) {
|
|
111518
111557
|
const name2 = typeof raw["topic"] === "string" ? raw["topic"] : "";
|
|
@@ -111549,6 +111588,10 @@ function schemaFor(tool) {
|
|
|
111549
111588
|
return GUIDE_TOOL.inputSchema;
|
|
111550
111589
|
if (tool === WAIT_TOOL.name)
|
|
111551
111590
|
return WAIT_TOOL.inputSchema;
|
|
111591
|
+
if (tool === SIGN_IN_TOOL.name)
|
|
111592
|
+
return SIGN_IN_TOOL.inputSchema;
|
|
111593
|
+
if (WEBSITE_NAMES.has(tool))
|
|
111594
|
+
return NO_OPTIONS;
|
|
111552
111595
|
const editing = EDITING.get(tool);
|
|
111553
111596
|
if (editing !== void 0)
|
|
111554
111597
|
return editing.inputSchema;
|
|
@@ -111570,6 +111613,8 @@ async function callToolAsync(tool, args2, ctx, label = nowCalled(tool)) {
|
|
|
111570
111613
|
return { content: [{ type: "text", text: refused3 }], isError: true };
|
|
111571
111614
|
return { content: [{ type: "text", text: NOTHING_GOING }] };
|
|
111572
111615
|
}
|
|
111616
|
+
if (tool === SIGN_IN_TOOL.name || WEBSITE_NAMES.has(tool))
|
|
111617
|
+
return { content: [{ type: "text", text: ON_YOUR_MACHINE }], isError: true };
|
|
111573
111618
|
const editing = EDITING.get(tool);
|
|
111574
111619
|
if (editing !== void 0) {
|
|
111575
111620
|
const refused3 = admitArgs(editing.inputSchema, raw, label);
|
|
@@ -111637,13 +111682,18 @@ function toolList() {
|
|
|
111637
111682
|
return [
|
|
111638
111683
|
GUIDE_TOOL,
|
|
111639
111684
|
WAIT_TOOL,
|
|
111685
|
+
...WEBSITE_TOOLS,
|
|
111686
|
+
SIGN_IN_TOOL,
|
|
111640
111687
|
...EDIT_TOOLS.map((tool) => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })),
|
|
111641
111688
|
...CORE_TOOLS.map((name2) => ({ name: name2, description: CORE_LINES.get(name2) ?? name2, inputSchema: schemaFor(name2) }))
|
|
111642
111689
|
];
|
|
111643
111690
|
}
|
|
111644
111691
|
var READING_TOOLS = /* @__PURE__ */ new Set([
|
|
111692
|
+
// The account read and signed in again too, so an agent in a read-only workspace can still move to another.
|
|
111645
111693
|
"guide",
|
|
111646
111694
|
"wait_for_calls",
|
|
111695
|
+
...Object.values(WEBSITE_READS),
|
|
111696
|
+
"sign_in",
|
|
111647
111697
|
"open_game",
|
|
111648
111698
|
"read_scene",
|
|
111649
111699
|
"read_type",
|
|
@@ -111668,6 +111718,7 @@ var READING_TOOLS = /* @__PURE__ */ new Set([
|
|
|
111668
111718
|
"app_online_logs",
|
|
111669
111719
|
"app_online_query"
|
|
111670
111720
|
]);
|
|
111721
|
+
var ON_YOUR_MACHINE = "This runs on your own machine, not on the website. Add Gamesteel to your agent with `npx gamesteel@latest connect`, or `claude mcp add --scope user gamesteel -- npx -y gamesteel@latest`, then ask again.";
|
|
111671
111722
|
function makesGame(name2, args2, exists) {
|
|
111672
111723
|
if (name2 === "new_game")
|
|
111673
111724
|
return true;
|
|
@@ -116168,6 +116219,18 @@ var FONT_FILES = {
|
|
|
116168
116219
|
ui: resolve2("@fontsource-variable/geist/files/geist-latin-wght-normal.woff2")
|
|
116169
116220
|
};
|
|
116170
116221
|
|
|
116222
|
+
// ../design/dist/roles.js
|
|
116223
|
+
var PERMISSIONS = ["play", "edit", "publish", "servers", "members", "billing", "workspace"];
|
|
116224
|
+
var GRANTS = {
|
|
116225
|
+
owner: new Set(PERMISSIONS),
|
|
116226
|
+
admin: /* @__PURE__ */ new Set(["play", "edit", "publish", "servers", "members"]),
|
|
116227
|
+
member: /* @__PURE__ */ new Set(["play", "edit"]),
|
|
116228
|
+
viewer: /* @__PURE__ */ new Set(["play"])
|
|
116229
|
+
};
|
|
116230
|
+
function can(role, permission) {
|
|
116231
|
+
return role != null && GRANTS[role].has(permission);
|
|
116232
|
+
}
|
|
116233
|
+
|
|
116171
116234
|
// ../i18n/dist/index.js
|
|
116172
116235
|
function chooseLanguage(header2) {
|
|
116173
116236
|
const best = { en: { q: 0, at: Infinity }, es: { q: 0, at: Infinity } };
|
|
@@ -116214,6 +116277,8 @@ var SITE = resolve3(dirname8(__gamesteelResolve("@gamesteel/site/package.json"))
|
|
|
116214
116277
|
var WORDS = resolve3(SITE, "..", "i18n");
|
|
116215
116278
|
var KEEP_LANGUAGE = 365 * 24 * 60 * 60;
|
|
116216
116279
|
var KEEP_FONT = 7 * 24 * 60 * 60;
|
|
116280
|
+
var PUBLIC_PAGES = ["/", "/engine", "/updates", "/demo", "/connect", "/pricing", "/docs", "/terms", "/privacy"];
|
|
116281
|
+
var PUBLIC = new Set(PUBLIC_PAGES);
|
|
116217
116282
|
var gzipped = promisify(gzip);
|
|
116218
116283
|
|
|
116219
116284
|
// ../studio/dist/server/export.js
|
|
@@ -121879,7 +121944,7 @@ function hostedAppRoutes(options) {
|
|
|
121879
121944
|
const mayExport = options.mayExport ?? ((req2) => requestPlaces.get(req2)?.export !== false);
|
|
121880
121945
|
const mayKeepKeys = options.mayKeepKeys ?? ((req2) => {
|
|
121881
121946
|
const role = requestPlaces.get(req2)?.role;
|
|
121882
|
-
return !agentRequests.has(req2) && (role
|
|
121947
|
+
return !agentRequests.has(req2) && can(role, "publish");
|
|
121883
121948
|
});
|
|
121884
121949
|
const gameOf = (params) => {
|
|
121885
121950
|
const slug = params["slug"] ?? "";
|
|
@@ -127834,6 +127899,7 @@ var HOUR = 36e5;
|
|
|
127834
127899
|
var DAY = 24 * HOUR;
|
|
127835
127900
|
var SESSION_LIFE = 30 * DAY;
|
|
127836
127901
|
var FREE_WEEK = 7 * DAY;
|
|
127902
|
+
var PICTURE_MOST = 512 * 1024;
|
|
127837
127903
|
|
|
127838
127904
|
// ../accounts/dist/limits.js
|
|
127839
127905
|
var MINUTE = 6e4;
|
|
@@ -127847,6 +127913,8 @@ var LIMITS2 = {
|
|
|
127847
127913
|
loginAddress: { tries: 30, per: 15 * MINUTE },
|
|
127848
127914
|
/** Sign-ups from one address. */
|
|
127849
127915
|
signup: { tries: 5, per: HOUR2 },
|
|
127916
|
+
/** Google log-ins started from one address, each keeping a state until it comes back (the Google log-in spec). */
|
|
127917
|
+
googleStart: { tries: 30, per: 15 * MINUTE },
|
|
127850
127918
|
/** Requests that can email an address (sign up, send again, forgot), counted whether or not one goes out. */
|
|
127851
127919
|
emails: { tries: 3, per: HOUR2 },
|
|
127852
127920
|
/** Apps registering to sign agents in, from one address (the agents by address spec, part 2). */
|
|
@@ -127858,6 +127926,9 @@ var LIMITS2 = {
|
|
|
127858
127926
|
oauthTokenAll: { tries: 600, per: MINUTE }
|
|
127859
127927
|
};
|
|
127860
127928
|
|
|
127929
|
+
// ../accounts/dist/mail.js
|
|
127930
|
+
var INK = { band: PALETTE2.bg, red: PALETTE2.forge, link: "#C81516", page: "#F2F2F3", card: "#FFFFFF", heading: "#0B0B0C", text: "#3F3F46", small: "#52525B", faint: "#A1A1AA", foot: "#FAFAFA", rule: "#ECECEE" };
|
|
127931
|
+
|
|
127861
127932
|
// ../accounts/dist/workspaces.js
|
|
127862
127933
|
var DAY2 = 864e5;
|
|
127863
127934
|
var INVITE_LIFE = 7 * DAY2;
|
|
@@ -134850,6 +134921,11 @@ var SiteRefusal = class extends Error {
|
|
|
134850
134921
|
status;
|
|
134851
134922
|
body;
|
|
134852
134923
|
};
|
|
134924
|
+
var SignInMoved = class extends SiteRefusal {
|
|
134925
|
+
constructor() {
|
|
134926
|
+
super(409, "this program's sign-in moved to another account or workspace: ask again", { error: "workspace" });
|
|
134927
|
+
}
|
|
134928
|
+
};
|
|
134853
134929
|
var pathOf3 = (path) => path.split("/").map(encodeURIComponent).join("/");
|
|
134854
134930
|
var sha2562 = (bytes2) => createHash5("sha256").update(bytes2).digest("hex");
|
|
134855
134931
|
var DeviceSite = class {
|
|
@@ -134862,11 +134938,19 @@ var DeviceSite = class {
|
|
|
134862
134938
|
get site() {
|
|
134863
134939
|
return this.options.site;
|
|
134864
134940
|
}
|
|
134941
|
+
/** The workspace the program started in, named in each request once it is known, so a sign-in that moved under the
|
|
134942
|
+
* program to another workspace is refused there, and nothing of this one is ever sent into it. */
|
|
134943
|
+
pinned = null;
|
|
134944
|
+
pin(workspaceId) {
|
|
134945
|
+
this.pinned = workspaceId;
|
|
134946
|
+
}
|
|
134865
134947
|
async request(method, path, init2 = {}) {
|
|
134948
|
+
const pinned = init2.unpinned === true ? null : this.pinned;
|
|
134866
134949
|
const headers = {
|
|
134867
134950
|
authorization: `Bearer ${await this.options.token()}`,
|
|
134868
134951
|
"x-gamesteel-engine": ENGINE_VERSION,
|
|
134869
134952
|
"x-gamesteel-session": init2.session ?? this.options.session(),
|
|
134953
|
+
...pinned === null ? {} : { "x-gamesteel-workspace": pinned },
|
|
134870
134954
|
...init2.headers
|
|
134871
134955
|
};
|
|
134872
134956
|
if (init2.json !== void 0) headers["content-type"] = "application/json";
|
|
@@ -134883,6 +134967,13 @@ var DeviceSite = class {
|
|
|
134883
134967
|
await response.body?.cancel();
|
|
134884
134968
|
throw new SiteRefusal(401, `this program is signed out of ${this.options.site}: sign in again`, null);
|
|
134885
134969
|
}
|
|
134970
|
+
if (response.status === 409 && pinned !== null) {
|
|
134971
|
+
const said4 = await response.clone().json().catch(() => null);
|
|
134972
|
+
if (said4?.error === "workspace") {
|
|
134973
|
+
await response.body?.cancel();
|
|
134974
|
+
throw new SignInMoved();
|
|
134975
|
+
}
|
|
134976
|
+
}
|
|
134886
134977
|
return response;
|
|
134887
134978
|
}
|
|
134888
134979
|
/** The answer's body when its status is one the route answers with, else thrown in its words. */
|
|
@@ -134930,8 +135021,21 @@ var DeviceSite = class {
|
|
|
134930
135021
|
async githubConfirmed(confirmation) {
|
|
134931
135022
|
return (await this.answer(await this.request("POST", "github/confirmed", { json: confirmation }), [200])).confirmed;
|
|
134932
135023
|
}
|
|
135024
|
+
/** Who the sign-in is now, whatever workspace the program started in. */
|
|
134933
135025
|
async standing() {
|
|
134934
|
-
return this.answer(await this.request("GET", "standing"), [200]);
|
|
135026
|
+
return this.answer(await this.request("GET", "standing", { unpinned: true }), [200]);
|
|
135027
|
+
}
|
|
135028
|
+
/** The person's workspaces, their role in each, and the one this works in (the website tool). */
|
|
135029
|
+
async workspaces() {
|
|
135030
|
+
return (await this.answer(await this.request("GET", "workspaces"), [200])).workspaces;
|
|
135031
|
+
}
|
|
135032
|
+
/** The workspace's people and their roles. */
|
|
135033
|
+
async members() {
|
|
135034
|
+
return (await this.answer(await this.request("GET", "members"), [200])).members;
|
|
135035
|
+
}
|
|
135036
|
+
/** What the workspace keeps, game by game: each item, its size, and whether its game uses it. */
|
|
135037
|
+
async storage() {
|
|
135038
|
+
return this.answer(await this.request("GET", "storage"), [200]);
|
|
134935
135039
|
}
|
|
134936
135040
|
/** A person of the workspace by name, or their agent. */
|
|
134937
135041
|
async name(user, grant) {
|
|
@@ -136966,6 +137070,7 @@ var GitHubClient = class {
|
|
|
136966
137070
|
}
|
|
136967
137071
|
const response = await this.fetch(`${this.api}${path}`, {
|
|
136968
137072
|
method,
|
|
137073
|
+
cache: "no-cache",
|
|
136969
137074
|
headers: {
|
|
136970
137075
|
authorization: `Bearer ${await this.options.token()}`,
|
|
136971
137076
|
accept: accept2,
|
|
@@ -137581,6 +137686,26 @@ var SignIn = class {
|
|
|
137581
137686
|
signedIn() {
|
|
137582
137687
|
return this.options.key !== null || this.read() !== null;
|
|
137583
137688
|
}
|
|
137689
|
+
/** The sign-in the program holds now, by its client (each sign-in registers its own), or the key; null for none.
|
|
137690
|
+
* Another sign-in on this machine changes it under every program running. */
|
|
137691
|
+
current() {
|
|
137692
|
+
return this.options.key !== null ? "key" : this.read()?.clientId ?? null;
|
|
137693
|
+
}
|
|
137694
|
+
/** This machine's sign-in ended for every program on it, and revoked on the website, so it leaves the account's
|
|
137695
|
+
* connected apps; the next call signs in afresh, as another account or into another workspace (a person with two
|
|
137696
|
+
* accounts, 2026-10-26). A website that cannot be reached now keeps the grant, which is forgotten here all the same. */
|
|
137697
|
+
async forget() {
|
|
137698
|
+
this.close();
|
|
137699
|
+
const held = await this.locked(async () => {
|
|
137700
|
+
const was = this.read();
|
|
137701
|
+
if (was !== null) this.write(null);
|
|
137702
|
+
return was;
|
|
137703
|
+
});
|
|
137704
|
+
if (held === null) return;
|
|
137705
|
+
await this.form("/oauth/revoke", { token: held.refresh }).then(async (answer3) => {
|
|
137706
|
+
await answer3.body?.cancel();
|
|
137707
|
+
}, () => void 0);
|
|
137708
|
+
}
|
|
137584
137709
|
/** A live token: the key, or the access token, refreshed when it ends within a minute. Throws SignInNeeded. */
|
|
137585
137710
|
async token() {
|
|
137586
137711
|
if (this.options.key !== null) return this.options.key;
|
|
@@ -139163,6 +139288,90 @@ function processLink() {
|
|
|
139163
139288
|
};
|
|
139164
139289
|
}
|
|
139165
139290
|
|
|
139291
|
+
// src/program/website.ts
|
|
139292
|
+
var ANOTHER = "For another account or workspace: website { action: 'sign_in' }.";
|
|
139293
|
+
var whoOf = (standing2) => `${standing2.email == null ? "" : ` as ${standing2.email}`}${standing2.workspaceName === void 0 ? "" : ` in the workspace ${standing2.workspaceName}`}`;
|
|
139294
|
+
function planSaid(standing2) {
|
|
139295
|
+
const plan = standing2.plan === null ? null : planById(standing2.plan).name;
|
|
139296
|
+
switch (standing2.state) {
|
|
139297
|
+
case "unlimited":
|
|
139298
|
+
return "has every feature on";
|
|
139299
|
+
case "free-week":
|
|
139300
|
+
return "is in its free week";
|
|
139301
|
+
case "active":
|
|
139302
|
+
return `is on the ${plan ?? ""} plan`;
|
|
139303
|
+
case "past-due":
|
|
139304
|
+
return `is on the ${plan ?? ""} plan, its payment past due`;
|
|
139305
|
+
case "ended":
|
|
139306
|
+
return "is read-only: its free week or plan has ended";
|
|
139307
|
+
default:
|
|
139308
|
+
return `is ${standing2.state}`;
|
|
139309
|
+
}
|
|
139310
|
+
}
|
|
139311
|
+
function accountSaid(standing2, site) {
|
|
139312
|
+
const { used, allowed } = standing2.storage ?? { used: 0, allowed: null };
|
|
139313
|
+
const keeps = allowed === null ? `${sizeText(used)}, with no limit` : `${sizeText(used)} of ${sizeText(allowed)}`;
|
|
139314
|
+
const { games, gameBytes } = standing2.limits;
|
|
139315
|
+
const makes = [
|
|
139316
|
+
games === null ? "any number of games" : `${String(games)} game${games === 1 ? "" : "s"}`,
|
|
139317
|
+
gameBytes === void 0 ? null : `each up to ${sizeText(gameBytes)}`
|
|
139318
|
+
].filter((part2) => part2 !== null).join(", ");
|
|
139319
|
+
return [
|
|
139320
|
+
`Signed in${whoOf(standing2)}, as its ${standing2.role}.`,
|
|
139321
|
+
`The workspace ${planSaid(standing2)}, and keeps ${keeps}. Its plan makes ${makes}${standing2.limits.export ? "" : ", and does not export"}.`,
|
|
139322
|
+
`The person's pages: their games ${site}/editor, what the workspace keeps ${site}/editor#storage, the plan ${site}/editor#plan.`,
|
|
139323
|
+
ANOTHER
|
|
139324
|
+
].join(" ");
|
|
139325
|
+
}
|
|
139326
|
+
function workspacesSaid(workspaces) {
|
|
139327
|
+
const lines = workspaces.map((one2) => `- ${one2.name}: ${one2.role}${one2.here ? " (this works in it)" : ""}`);
|
|
139328
|
+
return [`The person's workspaces, ${String(workspaces.length)}:`, ...lines, `To work in another: website { action: 'sign_in' }, and choose it on the page.`].join("\n");
|
|
139329
|
+
}
|
|
139330
|
+
function membersSaid(members, site) {
|
|
139331
|
+
const lines = members.map((one2) => `- ${one2.name === one2.email ? one2.email : `${one2.name} (${one2.email})`}: ${one2.role}${one2.you ? " (the person)" : ""}`);
|
|
139332
|
+
return [`The workspace's people, ${String(members.length)}:`, ...lines, `Its owner and admins invite and remove people at ${site}/editor#organization.`].join("\n");
|
|
139333
|
+
}
|
|
139334
|
+
var KINDS3 = {
|
|
139335
|
+
picture: "picture",
|
|
139336
|
+
sound: "sound",
|
|
139337
|
+
music: "music",
|
|
139338
|
+
font: "font",
|
|
139339
|
+
film: "film",
|
|
139340
|
+
replay: "replay",
|
|
139341
|
+
store: "store picture",
|
|
139342
|
+
game: "game text and settings",
|
|
139343
|
+
other: "file"
|
|
139344
|
+
};
|
|
139345
|
+
var PLURAL = {
|
|
139346
|
+
picture: "pictures",
|
|
139347
|
+
sound: "sounds",
|
|
139348
|
+
music: "music",
|
|
139349
|
+
font: "fonts",
|
|
139350
|
+
film: "films",
|
|
139351
|
+
replay: "replays",
|
|
139352
|
+
store: "store pictures",
|
|
139353
|
+
game: "game text and settings",
|
|
139354
|
+
other: "other files"
|
|
139355
|
+
};
|
|
139356
|
+
var LARGEST = 10;
|
|
139357
|
+
function storageSaid(storage, standing2, site) {
|
|
139358
|
+
const items = storage.games.flatMap((game) => game.items.map((item) => ({ ...item, game: game.title ?? game.slug })));
|
|
139359
|
+
const used = standing2.storage?.used ?? items.reduce((sum, item) => sum + item.bytes, 0) + storage.styles.bytes;
|
|
139360
|
+
const allowed = standing2.storage?.allowed ?? null;
|
|
139361
|
+
const kinds = /* @__PURE__ */ new Map();
|
|
139362
|
+
for (const item of items) kinds.set(item.kind, (kinds.get(item.kind) ?? 0) + item.bytes);
|
|
139363
|
+
const largest = [...items].sort((a4, b5) => b5.bytes - a4.bytes).slice(0, LARGEST);
|
|
139364
|
+
const unused = items.filter((item) => item.used === false && !item.kept);
|
|
139365
|
+
const useOf = (item) => item.kept ? "part of the game" : item.used === null ? "not checked" : item.used ? "in use" : "not in use";
|
|
139366
|
+
return [
|
|
139367
|
+
`The workspace keeps ${sizeText(used)}${allowed === null ? ", with no limit" : ` of ${sizeText(allowed)}`}, in ${String(storage.games.length)} game${storage.games.length === 1 ? "" : "s"}.`,
|
|
139368
|
+
kinds.size === 0 ? null : `By kind: ${[...kinds].sort((a4, b5) => b5[1] - a4[1]).map(([kind, bytes2]) => `${PLURAL[kind] ?? kind} ${sizeText(bytes2)}`).join(", ")}.`,
|
|
139369
|
+
largest.length === 0 ? null : "Largest:",
|
|
139370
|
+
...largest.map((item) => `- ${item.kind === "game" ? "the game itself" : item.name}, ${KINDS3[item.kind] ?? item.kind} of ${item.game}: ${sizeText(item.bytes)}, ${useOf(item)}`),
|
|
139371
|
+
unused.length === 0 ? "No game is known not to use anything it keeps." : `Not in use by their games: ${String(unused.length)}, ${sizeText(unused.reduce((sum, item) => sum + item.bytes, 0))}. The person deletes them at ${site}/editor#storage, where each says its game and whether it is used.`
|
|
139372
|
+
].filter((line2) => line2 !== null).join("\n");
|
|
139373
|
+
}
|
|
139374
|
+
|
|
139166
139375
|
// src/program/program.ts
|
|
139167
139376
|
var STANDING_MS = 3e4;
|
|
139168
139377
|
var OLD_EXPORT_BYTES = 100 * MB;
|
|
@@ -139172,6 +139381,7 @@ var signInFirst = (needed) => ({
|
|
|
139172
139381
|
${needed.message}` }]
|
|
139173
139382
|
});
|
|
139174
139383
|
var clientName = (name2) => (name2 ?? "agent").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "agent";
|
|
139384
|
+
var movedFrom = (was, now) => was.workspaceId !== now.workspaceId || was.userId !== now.userId || was.grantId !== now.grantId;
|
|
139175
139385
|
async function startProgram(options) {
|
|
139176
139386
|
const { settings, signIn } = options;
|
|
139177
139387
|
const log = options.log ?? ((line2) => {
|
|
@@ -139200,9 +139410,11 @@ async function startProgram(options) {
|
|
|
139200
139410
|
let standingAt = 0;
|
|
139201
139411
|
let standing2 = null;
|
|
139202
139412
|
const start2 = async () => {
|
|
139413
|
+
const signedWith = signIn.current();
|
|
139203
139414
|
const known2 = await site.standing();
|
|
139204
139415
|
standing2 = known2;
|
|
139205
139416
|
standingAt = Date.now();
|
|
139417
|
+
site.pin(known2.workspaceId);
|
|
139206
139418
|
const grantId = known2.grantId ?? "";
|
|
139207
139419
|
session = `${settings.programId}:${clientName(server.getClientVersion()?.name)}`;
|
|
139208
139420
|
const author = `ai:${grantId}:${session}`;
|
|
@@ -139369,6 +139581,7 @@ async function startProgram(options) {
|
|
|
139369
139581
|
madeStores = publishing;
|
|
139370
139582
|
return {
|
|
139371
139583
|
standing: known2,
|
|
139584
|
+
signedWith,
|
|
139372
139585
|
copy,
|
|
139373
139586
|
uploader: sending,
|
|
139374
139587
|
follower,
|
|
@@ -139396,9 +139609,24 @@ async function startProgram(options) {
|
|
|
139396
139609
|
const listen = () => {
|
|
139397
139610
|
if (signIn.signedIn()) desk.start();
|
|
139398
139611
|
};
|
|
139612
|
+
let ending = Promise.resolve();
|
|
139613
|
+
const restart = (from = running) => {
|
|
139614
|
+
if (from === null || running !== from) return ending;
|
|
139615
|
+
const was = running;
|
|
139616
|
+
running = null;
|
|
139617
|
+
standing2 = null;
|
|
139618
|
+
current = null;
|
|
139619
|
+
told = false;
|
|
139620
|
+
storageTold = false;
|
|
139621
|
+
nearTold.clear();
|
|
139622
|
+
if (was !== null) ending = ending.then(async () => {
|
|
139623
|
+
await (await was.catch(() => null))?.close();
|
|
139624
|
+
});
|
|
139625
|
+
return ending;
|
|
139626
|
+
};
|
|
139399
139627
|
const prepared = () => {
|
|
139400
139628
|
if (running === null) {
|
|
139401
|
-
const starting = start2
|
|
139629
|
+
const starting = ending.then(start2);
|
|
139402
139630
|
running = starting;
|
|
139403
139631
|
starting.catch(() => {
|
|
139404
139632
|
if (running === starting) running = null;
|
|
@@ -139426,20 +139654,67 @@ async function startProgram(options) {
|
|
|
139426
139654
|
return `${slug} holds ${sizeText(bytes2)} of the ${sizeText(cap)} a game may hold on this plan. Past that it takes no new files, though it still saves; its owner can choose a bigger plan at ${settings.site}/editor#plan.`;
|
|
139427
139655
|
};
|
|
139428
139656
|
const gamesHere = (root2) => new Set(readdirSync17(root2).filter((slug) => existsSync26(join40(root2, slug, "game.json"))));
|
|
139657
|
+
const signInAgain = async () => {
|
|
139658
|
+
if (settings.key !== null) {
|
|
139659
|
+
return refusal3("this program signs in with a personal key (GAMESTEEL_KEY), which is of one account and workspace: to work as another, give it a key made there, on the editor's Agents page");
|
|
139660
|
+
}
|
|
139661
|
+
const was = (await running?.catch(() => null))?.standing ?? standing2;
|
|
139662
|
+
await restart();
|
|
139663
|
+
await signIn.forget();
|
|
139664
|
+
const needed = new SignInNeeded(await signIn.address());
|
|
139665
|
+
const from = was === null ? "" : whoOf(was);
|
|
139666
|
+
return { content: [{ type: "text", text: `Gamesteel signed out${from}, so nothing else was done. On the page, the person can use another account and chooses the workspace.
|
|
139667
|
+
${needed.message}` }] };
|
|
139668
|
+
};
|
|
139669
|
+
const websiteSaid = async (name2, now) => {
|
|
139670
|
+
switch (name2) {
|
|
139671
|
+
case WEBSITE_READS.account:
|
|
139672
|
+
return accountSaid(now, settings.site);
|
|
139673
|
+
case WEBSITE_READS.workspaces:
|
|
139674
|
+
return workspacesSaid(await site.workspaces());
|
|
139675
|
+
case WEBSITE_READS.members:
|
|
139676
|
+
return membersSaid(await site.members(), settings.site);
|
|
139677
|
+
case WEBSITE_READS.storage:
|
|
139678
|
+
return storageSaid(await site.storage(), now, settings.site);
|
|
139679
|
+
default:
|
|
139680
|
+
return null;
|
|
139681
|
+
}
|
|
139682
|
+
};
|
|
139429
139683
|
const around2 = async (name2, args2, call) => {
|
|
139684
|
+
if (name2 === SIGN_IN_TOOL.name) return signInAgain();
|
|
139430
139685
|
let program;
|
|
139431
139686
|
let now;
|
|
139687
|
+
let switched = null;
|
|
139688
|
+
let on2 = null;
|
|
139432
139689
|
try {
|
|
139433
139690
|
if (!signIn.signedIn()) throw new SignInNeeded(await signIn.address());
|
|
139434
|
-
|
|
139691
|
+
on2 = prepared();
|
|
139692
|
+
program = await on2;
|
|
139693
|
+
if (signIn.current() !== program.signedWith || name2 === WEBSITE_READS.account || name2 === WEBSITE_READS.storage) standing2 = null;
|
|
139435
139694
|
now = await plan();
|
|
139695
|
+
if (movedFrom(program.standing, now)) {
|
|
139696
|
+
await restart(on2);
|
|
139697
|
+
on2 = prepared();
|
|
139698
|
+
program = await on2;
|
|
139699
|
+
now = await plan();
|
|
139700
|
+
switched = `Gamesteel's sign-in on this computer changed: it works${whoOf(now)} now.`;
|
|
139701
|
+
}
|
|
139436
139702
|
listen();
|
|
139437
139703
|
} catch (error2) {
|
|
139438
139704
|
if (error2 instanceof SignInNeeded) return signInFirst(error2);
|
|
139439
139705
|
if (error2 instanceof SiteRefusal && error2.status === 401) return signInFirst(new SignInNeeded(await signIn.address()));
|
|
139706
|
+
if (error2 instanceof SignInMoved) {
|
|
139707
|
+
await restart(on2);
|
|
139708
|
+
return refusal3(error2.message);
|
|
139709
|
+
}
|
|
139440
139710
|
return refusal3(`the website could not be reached: ${error2.message}. Ask again in a moment`);
|
|
139441
139711
|
}
|
|
139442
139712
|
current = program.ctx;
|
|
139713
|
+
const website = await websiteSaid(name2, now).catch((error2) => ({ refused: error2.message }));
|
|
139714
|
+
if (typeof website === "object" && website !== null) return refusal3(website.refused);
|
|
139715
|
+
if (website !== null) return { content: [{ type: "text", text: switched === null ? website : `${switched}
|
|
139716
|
+
|
|
139717
|
+
${website}` }] };
|
|
139443
139718
|
const { copy, follower, team: team2, author, uploader, moves: moves2 } = program;
|
|
139444
139719
|
const reading = READING_TOOLS.has(name2) || name2 === "team" && args2["action"] === "read";
|
|
139445
139720
|
if (!reading && !now.limits.writes) {
|
|
@@ -139486,6 +139761,7 @@ async function startProgram(options) {
|
|
|
139486
139761
|
}
|
|
139487
139762
|
if (unsaved.length > 0) pending.push(...(await uploader.send(unsaved)).pending);
|
|
139488
139763
|
} catch (error2) {
|
|
139764
|
+
if (error2 instanceof SignInMoved) await restart(on2);
|
|
139489
139765
|
return refusal3(error2.message);
|
|
139490
139766
|
}
|
|
139491
139767
|
const cap = now.limits.exportBytes;
|
|
@@ -139532,6 +139808,11 @@ ${line2}` }] };
|
|
|
139532
139808
|
${line2}` }] };
|
|
139533
139809
|
}
|
|
139534
139810
|
}
|
|
139811
|
+
if (name2 === "list_games" && answer3.isError !== true && now.email != null) {
|
|
139812
|
+
answer3 = { ...answer3, content: [...answer3.content, { type: "text", text: `
|
|
139813
|
+
|
|
139814
|
+
Signed in${whoOf(now)}. For another account or workspace: website { action: 'sign_in' }.` }] };
|
|
139815
|
+
}
|
|
139535
139816
|
if (name2 === "list_games" && unread.length > 0) {
|
|
139536
139817
|
answer3 = { ...answer3, content: [...answer3.content, { type: "text", text: `
|
|
139537
139818
|
|
|
@@ -139550,6 +139831,9 @@ Not on the website yet: ${pending.join("; ")}.` }] };
|
|
|
139550
139831
|
const team3 = program.standing.team;
|
|
139551
139832
|
answer3 = withFirstWords(answer3, team3 === null ? null : teamInstructions({ agent: team3.agent, workspace: team3.workspace, people: [...team3.people] }));
|
|
139552
139833
|
}
|
|
139834
|
+
if (switched !== null) answer3 = { ...answer3, content: [{ type: "text", text: `${switched}
|
|
139835
|
+
|
|
139836
|
+
` }, ...answer3.content] };
|
|
139553
139837
|
return answer3;
|
|
139554
139838
|
};
|
|
139555
139839
|
serveTools(server, {
|
|
@@ -139572,6 +139856,7 @@ Not on the website yet: ${pending.join("; ")}.` }] };
|
|
|
139572
139856
|
await desk.close();
|
|
139573
139857
|
signIn.close();
|
|
139574
139858
|
if (running !== null) await (await running.catch(() => null))?.close();
|
|
139859
|
+
await ending;
|
|
139575
139860
|
})();
|
|
139576
139861
|
return closing;
|
|
139577
139862
|
}
|
|
@@ -85761,6 +85761,7 @@ var PLANS = [
|
|
|
85761
85761
|
monthly: 999,
|
|
85762
85762
|
seats: 1,
|
|
85763
85763
|
extraSeat: null,
|
|
85764
|
+
storageBlock: 499,
|
|
85764
85765
|
everythingIn: null,
|
|
85765
85766
|
pick: false,
|
|
85766
85767
|
storage: 10 * GB,
|
|
@@ -85768,7 +85769,7 @@ var PLANS = [
|
|
|
85768
85769
|
includes: [
|
|
85769
85770
|
room(10 * GB, 500 * MB2),
|
|
85770
85771
|
line("Everything Gamesteel does, with your own agent"),
|
|
85771
|
-
line("The agent's
|
|
85772
|
+
line("The agent's 16 tools"),
|
|
85772
85773
|
line("Export to the web"),
|
|
85773
85774
|
line("Phone app builds")
|
|
85774
85775
|
]
|
|
@@ -85779,6 +85780,7 @@ var PLANS = [
|
|
|
85779
85780
|
monthly: 1999,
|
|
85780
85781
|
seats: 3,
|
|
85781
85782
|
extraSeat: 1e3,
|
|
85783
|
+
storageBlock: 399,
|
|
85782
85784
|
everythingIn: "starter",
|
|
85783
85785
|
pick: true,
|
|
85784
85786
|
storage: 50 * GB,
|
|
@@ -85786,11 +85788,12 @@ var PLANS = [
|
|
|
85786
85788
|
includes: [room(50 * GB, GB), line("An organization with shared games and roles")]
|
|
85787
85789
|
},
|
|
85788
85790
|
{
|
|
85789
|
-
id: "
|
|
85790
|
-
name: "
|
|
85791
|
+
id: "business",
|
|
85792
|
+
name: "Business",
|
|
85791
85793
|
monthly: 3999,
|
|
85792
85794
|
seats: 20,
|
|
85793
|
-
extraSeat:
|
|
85795
|
+
extraSeat: 800,
|
|
85796
|
+
storageBlock: 299,
|
|
85794
85797
|
everythingIn: "pro",
|
|
85795
85798
|
pick: false,
|
|
85796
85799
|
storage: 250 * GB,
|
|
@@ -85798,6 +85801,12 @@ var PLANS = [
|
|
|
85798
85801
|
includes: [room(250 * GB, 2 * GB), line("Invoices instead of cards"), line("Priority support")]
|
|
85799
85802
|
}
|
|
85800
85803
|
];
|
|
85804
|
+
var ENTERPRISE = {
|
|
85805
|
+
name: "Enterprise",
|
|
85806
|
+
everythingIn: "business",
|
|
85807
|
+
includes: [line("Seats and storage sized for your team"), line("Terms and invoicing agreed with you"), line("A direct line to the team")],
|
|
85808
|
+
email: "business@gamesteel.studio"
|
|
85809
|
+
};
|
|
85801
85810
|
var TRIAL = {
|
|
85802
85811
|
days: 7,
|
|
85803
85812
|
games: 1,
|
|
@@ -85807,7 +85816,7 @@ var TRIAL = {
|
|
|
85807
85816
|
gameBytes: 200 * MB2,
|
|
85808
85817
|
rules: ["One week, free", "One game", "No export", "A watermark on the game"]
|
|
85809
85818
|
};
|
|
85810
|
-
var STORAGE_BLOCK = { bytes: 10 * GB
|
|
85819
|
+
var STORAGE_BLOCK = { bytes: 10 * GB };
|
|
85811
85820
|
var UNLIMITED_GAME_BYTES = 2 * GB;
|
|
85812
85821
|
|
|
85813
85822
|
// ../agent/dist/export-tools.js
|
|
@@ -85815,7 +85824,8 @@ var NEEDS_PROGRAM6 = "exporting to a file runs in the Gamesteel program on your
|
|
|
85815
85824
|
var EXPORT_TOOLS = [
|
|
85816
85825
|
{
|
|
85817
85826
|
name: "export_game",
|
|
85818
|
-
|
|
85827
|
+
// Its words cut to make room under Cursor's list size for the website's own tool (2026-10-26).
|
|
85828
|
+
description: "write the game's export, a zip that plays anywhere, on this machine, and say where it is: unzipped, its index.html plays in a browser. A plan exports games up to its cap; a large game takes minutes, and memory.",
|
|
85819
85829
|
inputSchema: object({ game: GAME }, ["game"]),
|
|
85820
85830
|
handle: async (args, ctx) => {
|
|
85821
85831
|
const slug = textArg(args, "game");
|
|
@@ -91546,7 +91556,7 @@ var import_ajv_formats = __toESM(require_dist3(), 1);
|
|
|
91546
91556
|
// ../agent/dist/families.js
|
|
91547
91557
|
var fam = (name, about, actions) => ({ name, about, actions: Object.entries(actions).map(([action, tool]) => ({ action, tool })) });
|
|
91548
91558
|
var FAMILIES2 = [
|
|
91549
|
-
fam("games", "the games in the library
|
|
91559
|
+
fam("games", "the games in the library, and game text given as source", {
|
|
91550
91560
|
list: "list_games",
|
|
91551
91561
|
open: "open_game",
|
|
91552
91562
|
new: "new_game",
|
|
@@ -91573,7 +91583,7 @@ var FAMILIES2 = [
|
|
|
91573
91583
|
redo: "redo",
|
|
91574
91584
|
art: "undo_art"
|
|
91575
91585
|
}),
|
|
91576
|
-
fam("playtest", "play the game yourself, headless
|
|
91586
|
+
fam("playtest", "play the game yourself, headless, and look at it", {
|
|
91577
91587
|
play: "playtest_play",
|
|
91578
91588
|
until: "playtest_until",
|
|
91579
91589
|
look: "playtest_look",
|
|
@@ -91582,13 +91592,13 @@ var FAMILIES2 = [
|
|
|
91582
91592
|
snapshot: "playtest_snapshot",
|
|
91583
91593
|
restore: "playtest_restore"
|
|
91584
91594
|
}),
|
|
91585
|
-
fam("art", "a game's pictures
|
|
91595
|
+
fam("art", "a game's pictures, painted or modelled in 3D", {
|
|
91586
91596
|
paint: "paint_art",
|
|
91587
91597
|
model: "model_art",
|
|
91588
91598
|
read: "read_art",
|
|
91589
91599
|
list: "list_art"
|
|
91590
91600
|
}),
|
|
91591
|
-
fam("sound", "a game's sound
|
|
91601
|
+
fam("sound", "a game's sound effects and music", {
|
|
91592
91602
|
design: "design_sound",
|
|
91593
91603
|
compose: "compose_music",
|
|
91594
91604
|
listen: "listen",
|
|
@@ -91614,6 +91624,14 @@ var FAMILIES2 = [
|
|
|
91614
91624
|
online: "app_online",
|
|
91615
91625
|
online_logs: "app_online_logs",
|
|
91616
91626
|
online_query: "app_online_query"
|
|
91627
|
+
}),
|
|
91628
|
+
// The 16th (the owner, 2026-10-26): what is the website's, not a game's.
|
|
91629
|
+
fam("website", "your Gamesteel account on the website", {
|
|
91630
|
+
account: "website_account",
|
|
91631
|
+
workspaces: "website_workspaces",
|
|
91632
|
+
members: "website_members",
|
|
91633
|
+
storage: "website_storage",
|
|
91634
|
+
sign_in: "sign_in"
|
|
91617
91635
|
})
|
|
91618
91636
|
];
|
|
91619
91637
|
|
|
@@ -91648,6 +91666,15 @@ var WAIT_TOOL = {
|
|
|
91648
91666
|
description: `wait up to ${String(JOB_MS / 1e3)} seconds for a call of yours still going, and answer with what it said`,
|
|
91649
91667
|
inputSchema: { type: "object", additionalProperties: false, properties: {} }
|
|
91650
91668
|
};
|
|
91669
|
+
var WEBSITE_READS = { account: "website_account", workspaces: "website_workspaces", members: "website_members", storage: "website_storage" };
|
|
91670
|
+
var NO_OPTIONS = { type: "object", additionalProperties: false, properties: {} };
|
|
91671
|
+
var WEBSITE_TOOLS = [
|
|
91672
|
+
{ name: WEBSITE_READS.account, description: "which account and workspace this works in, its plan, limits and pages", inputSchema: NO_OPTIONS },
|
|
91673
|
+
{ name: WEBSITE_READS.workspaces, description: "the person's workspaces, their role in each, and which this works in", inputSchema: NO_OPTIONS },
|
|
91674
|
+
{ name: WEBSITE_READS.members, description: "the workspace's people and their roles", inputSchema: NO_OPTIONS },
|
|
91675
|
+
{ name: WEBSITE_READS.storage, description: "what the workspace keeps: by kind, the largest files, what no game uses", inputSchema: NO_OPTIONS }
|
|
91676
|
+
];
|
|
91677
|
+
var WEBSITE_NAMES = new Set(Object.values(WEBSITE_READS));
|
|
91651
91678
|
var EDITING = new Map(EDIT_TOOLS.map((tool) => [tool.name, tool]));
|
|
91652
91679
|
var CORE_LINES = /* @__PURE__ */ new Map([
|
|
91653
91680
|
["list_games", "the saved games in the library, newest first"],
|
|
@@ -91657,6 +91684,36 @@ var CORE_LINES = /* @__PURE__ */ new Map([
|
|
|
91657
91684
|
["create_game", "generate a seeded platform maze from a design; with save, keep it in the library as a game you can edit"]
|
|
91658
91685
|
]);
|
|
91659
91686
|
var CORE_TOOLS = TOOL_NAMES.filter((name) => !EDITING.has(name) && CORE_LINES.has(name));
|
|
91687
|
+
var READING_TOOLS = /* @__PURE__ */ new Set([
|
|
91688
|
+
// The account read and signed in again too, so an agent in a read-only workspace can still move to another.
|
|
91689
|
+
"guide",
|
|
91690
|
+
"wait_for_calls",
|
|
91691
|
+
...Object.values(WEBSITE_READS),
|
|
91692
|
+
"sign_in",
|
|
91693
|
+
"open_game",
|
|
91694
|
+
"read_scene",
|
|
91695
|
+
"read_type",
|
|
91696
|
+
"read_code",
|
|
91697
|
+
"changes_since",
|
|
91698
|
+
"list_art",
|
|
91699
|
+
"list_components",
|
|
91700
|
+
"describe_component",
|
|
91701
|
+
"list_sounds",
|
|
91702
|
+
"list_fonts",
|
|
91703
|
+
"read_art",
|
|
91704
|
+
"list_made",
|
|
91705
|
+
"search_code",
|
|
91706
|
+
"find_references",
|
|
91707
|
+
"list_games",
|
|
91708
|
+
"validate",
|
|
91709
|
+
"simulate",
|
|
91710
|
+
"replay",
|
|
91711
|
+
"github_status",
|
|
91712
|
+
// A game's online, its server's logs and its data, read only (the online services spec).
|
|
91713
|
+
"app_online",
|
|
91714
|
+
"app_online_logs",
|
|
91715
|
+
"app_online_query"
|
|
91716
|
+
]);
|
|
91660
91717
|
var EDIT_OPS = Object.keys(OP_FIELDS);
|
|
91661
91718
|
|
|
91662
91719
|
// ../core/dist/render/index.js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gamesteel",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "The Gamesteel program your AI agent starts, and the command that sets it up in Claude Code, Codex, Gemini CLI, Cursor, VS Code and 25 more. The work runs on your machine; the website keeps your games.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gamesteel",
|
|
@@ -39,23 +39,23 @@
|
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
40
40
|
"esbuild": "0.28.2",
|
|
41
41
|
"miniflare": "4.20260730.0",
|
|
42
|
+
"@gamesteel/accounts": "0.1.0",
|
|
42
43
|
"@gamesteel/builder": "0.1.0",
|
|
43
|
-
"@gamesteel/
|
|
44
|
+
"@gamesteel/billing": "0.1.0",
|
|
44
45
|
"@gamesteel/agent": "0.1.0",
|
|
46
|
+
"@gamesteel/connect": "0.1.0",
|
|
47
|
+
"@gamesteel/cloud": "0.1.0",
|
|
48
|
+
"@gamesteel/i18n": "0.1.0",
|
|
45
49
|
"@gamesteel/edit": "0.1.0",
|
|
50
|
+
"@gamesteel/model": "0.1.0",
|
|
46
51
|
"@gamesteel/core": "0.1.0",
|
|
47
|
-
"@gamesteel/
|
|
48
|
-
"@gamesteel/cloud": "0.1.0",
|
|
49
|
-
"@gamesteel/github": "0.1.0",
|
|
50
|
-
"@gamesteel/accounts": "0.1.0",
|
|
52
|
+
"@gamesteel/service": "0.1.0",
|
|
51
53
|
"@gamesteel/online": "0.1.0",
|
|
52
|
-
"@gamesteel/model": "0.1.0",
|
|
53
|
-
"@gamesteel/store": "0.1.0",
|
|
54
|
-
"@gamesteel/design": "0.1.0",
|
|
55
54
|
"@gamesteel/studio": "0.1.0",
|
|
56
|
-
"@gamesteel/service": "0.1.0",
|
|
57
55
|
"@gamesteel/stores": "0.1.0",
|
|
58
|
-
"@gamesteel/
|
|
56
|
+
"@gamesteel/github": "0.1.0",
|
|
57
|
+
"@gamesteel/design": "0.1.0",
|
|
58
|
+
"@gamesteel/store": "0.1.0"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"pretest": "pnpm --filter \"gamesteel^...\" --filter \"!@gamesteel/studio\" build && pnpm --filter @gamesteel/studio exec tsc -p tsconfig.json && pnpm build",
|