@maka/maka-cli 5.14.1 → 5.15.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.
@@ -0,0 +1,424 @@
1
+ /**
2
+ * THE THIN CLIENT (Phase C M4): shared runs live on maka-cli.com -- the
3
+ * server runs the engine, this module is the CLI's side of the wire.
4
+ * Everything rides @maka/meteor-sdk's DDP client (standing transport
5
+ * ruling): one connection per process, opened lazily at the hub, login
6
+ * by the same resume token cloud-saves stores. Every path degrades to a
7
+ * silent no-op when logged out, offline, or killed via MAKA_NO_DDP=1
8
+ * (harnesses) -- solo play must never notice this file exists.
9
+ *
10
+ * Three surfaces:
11
+ * - HubLink: the hub-side connection -- resume login, the invites
12
+ * subscription ("your commlink buzzes"), and method calls.
13
+ * - tryCreateSharedSession: the Krow-call upgrade -- ghost crew slots
14
+ * whose owners are ON the street right now become a real party, and
15
+ * the job drafts on the server (the seed never comes down).
16
+ * - SharedRunSession: session mode -- events stream into the blessed
17
+ * panes, typed input becomes sideQuest.command, death and settlement
18
+ * close the loop.
19
+ */
20
+ import { createRequire } from 'node:module';
21
+ import { Logger } from './logger.js';
22
+ import { authToken, fetchSave } from './cloud-saves.js';
23
+ import { saveSlug, restorePlayer, writeSaveAtomic } from './persistence.js';
24
+ const require = createRequire(import.meta.url);
25
+ const DEV = process.env.MAKA_DEV === 'True';
26
+ const BASE_URL = DEV
27
+ ? `http://localhost:${process.env.MAKA_DEV_PORT ?? 3000}`
28
+ : 'https://www.maka-cli.com';
29
+ function killed() {
30
+ return process.env.MAKA_NO_DDP === '1';
31
+ }
32
+ /** This build IS the engine the server runs -- the version gate compares
33
+ * our own package version against the server's pin. */
34
+ export function engineVersion() {
35
+ for (const rel of ['../../../../../package.json', '../../../../../../package.json']) {
36
+ try {
37
+ const pkg = require(rel);
38
+ if (pkg?.name === '@maka/maka-cli')
39
+ return pkg.version;
40
+ }
41
+ catch { /* try the next depth (src vs bundle layouts) */ }
42
+ }
43
+ return '0.0.0-unknown';
44
+ }
45
+ /**
46
+ * The one DDP connection this process holds. Opened in the background
47
+ * the first time the hub asks for it; the SDK's own retry machinery
48
+ * (backoff, re-subscribe, in-flight re-send) owns reconnects after that.
49
+ */
50
+ class HubLinkImpl {
51
+ conn;
52
+ connecting;
53
+ userId;
54
+ /** Session docs from the invites subscription, by id. */
55
+ sessions = new Map();
56
+ announced = new Set();
57
+ noticeShown = false;
58
+ /** Fire-and-forget warm-up from the hub -- never blocks a turn. */
59
+ ensure(game) {
60
+ if (killed() || this.conn || this.connecting)
61
+ return;
62
+ if (!authToken())
63
+ return;
64
+ void this.ready(game).catch(() => undefined);
65
+ }
66
+ /** The connection, established if needed. Undefined = offline/logged
67
+ * out (callers degrade); throws only never. */
68
+ async ready(game) {
69
+ if (killed())
70
+ return undefined;
71
+ if (this.conn)
72
+ return this.conn;
73
+ if (this.connecting)
74
+ return this.connecting;
75
+ const token = authToken();
76
+ if (!token)
77
+ return undefined;
78
+ this.connecting = (async () => {
79
+ try {
80
+ const sdk = require('@maka/meteor-sdk');
81
+ await sdk.init({ release: 'METEOR@3.5.1' });
82
+ const conn = await sdk.connectDdp(BASE_URL, { firstConnectTimeoutMs: 15000 });
83
+ const login = (await conn.call('login', { resume: token }));
84
+ this.userId = login?.id;
85
+ this.tapSessions(conn, game);
86
+ await conn.subscribe('sideQuest.invites');
87
+ this.conn = conn;
88
+ return conn;
89
+ }
90
+ catch (err) {
91
+ Logger.getInstance().write(`shared-run: hub link unavailable (${err?.message}).`);
92
+ if (!this.noticeShown && game) {
93
+ this.noticeShown = true;
94
+ // One notice, then silence -- the hub works fully offline.
95
+ Logger.getInstance().write(`shared-run: run invites offline this session.`);
96
+ }
97
+ return undefined;
98
+ }
99
+ finally {
100
+ this.connecting = undefined;
101
+ }
102
+ })();
103
+ return this.connecting;
104
+ }
105
+ /** Every GameRunSessions doc the server publishes to us, kept fresh
106
+ * from the raw DDP stream (added/changed/removed). */
107
+ tapSessions(conn, game) {
108
+ conn.raw._stream.on('message', (raw) => {
109
+ try {
110
+ const m = JSON.parse(raw);
111
+ if (m.collection !== 'GameRunSessions')
112
+ return;
113
+ if (m.msg === 'added') {
114
+ this.sessions.set(m.id, { ...(m.fields ?? {}) });
115
+ }
116
+ else if (m.msg === 'changed') {
117
+ const doc = this.sessions.get(m.id) ?? {};
118
+ Object.assign(doc, m.fields ?? {});
119
+ for (const c of m.cleared ?? [])
120
+ delete doc[c];
121
+ this.sessions.set(m.id, doc);
122
+ }
123
+ else if (m.msg === 'removed') {
124
+ this.sessions.delete(m.id);
125
+ return;
126
+ }
127
+ if (game)
128
+ this.maybeAnnounce(game);
129
+ }
130
+ catch { /* not json / not ours */ }
131
+ });
132
+ }
133
+ /** "Your commlink buzzes" -- once per session, when an invite goes
134
+ * live (status open and we're still 'invited'). */
135
+ maybeAnnounce(game) {
136
+ for (const [id, doc] of this.sessions) {
137
+ if (doc.status !== 'open' || this.announced.has(id))
138
+ continue;
139
+ const me = doc.party?.find(p => p.userID === this.userId);
140
+ if (me?.status !== 'invited')
141
+ continue;
142
+ this.announced.add(id);
143
+ const leader = doc.party?.find(p => p.role === 'leader');
144
+ Logger.getInstance().logWithColor(`📳 Your commlink buzzes -- ${leader?.actorName ?? 'a runner'} has a live job for the crew: "${doc.pitch ?? 'a run'}". ("call taxi" to ride.)`, 'green');
145
+ game.updateStatus();
146
+ }
147
+ }
148
+ /** The freshest OPEN session we're invited to (or reconnecting to). */
149
+ openInvite() {
150
+ for (const [id, doc] of this.sessions) {
151
+ if (doc.status !== 'open')
152
+ continue;
153
+ const me = doc.party?.find(p => p.userID === this.userId);
154
+ if (me && (me.status === 'invited' || me.status === 'disconnected' || me.status === 'joined')) {
155
+ return { sessionID: id, pitch: doc.pitch };
156
+ }
157
+ }
158
+ return undefined;
159
+ }
160
+ async call(name, params) {
161
+ const conn = await this.ready();
162
+ if (!conn)
163
+ throw new Error('offline');
164
+ return conn.call(name, params);
165
+ }
166
+ /** Scrap a server-side draft (party changed / decline). Silent. */
167
+ abortDraft(sessionID) {
168
+ void this.call('sideQuest.abortDraft', { sessionID }).catch(() => undefined);
169
+ }
170
+ }
171
+ export const HubLink = new HubLinkImpl();
172
+ /** Hub warm-up hook (Game.initEngine): connect + invites, in the
173
+ * background. */
174
+ export function ensureHubLink(game) {
175
+ HubLink.ensure(game);
176
+ }
177
+ /**
178
+ * Ghost crew slots whose owners are on the street right now become a
179
+ * REAL party: the job drafts on the server. Returns undefined when the
180
+ * shared path doesn't apply (no ghost crew, logged out, offline, or the
181
+ * server declines -- e.g. an owner just went dark); the caller falls
182
+ * back to the local draft with the ghosts as AI riders (Phase B).
183
+ */
184
+ export async function tryCreateSharedSession(game) {
185
+ if (killed())
186
+ return undefined;
187
+ const ghosts = game.crew.filter(m => m.source === 'ghost' && m.ghost);
188
+ if (ghosts.length === 0)
189
+ return undefined;
190
+ if (!authToken())
191
+ return undefined;
192
+ try {
193
+ const res = await HubLink.call('sideQuest.createSession', {
194
+ engineVersion: engineVersion(),
195
+ slug: saveSlug(game.player.name),
196
+ party: ghosts.map(g => ({ handle: g.ghost.owner, slug: g.ghost.slug })),
197
+ });
198
+ return res;
199
+ }
200
+ catch (err) {
201
+ const e = err;
202
+ Logger.getInstance().write(`shared-run: server draft declined (${e.error ?? ''} ${e.reason ?? e.message ?? ''}) -- falling back to local ghosts.`);
203
+ return undefined;
204
+ }
205
+ }
206
+ /**
207
+ * A live shared run, from this terminal's side: the server's event
208
+ * stream renders into the same blessed panes solo play uses, and every
209
+ * typed command ships to sideQuest.command. Installed as
210
+ * game.remoteSession -- Game.handleInput delegates here wholesale, so
211
+ * ui.ts needs no new wiring.
212
+ */
213
+ export class SharedRunSession {
214
+ game;
215
+ sessionID;
216
+ lastSeq = 0;
217
+ dead = false;
218
+ over = false;
219
+ quitArmed = false;
220
+ subs = [];
221
+ constructor(game, sessionID) {
222
+ this.game = game;
223
+ this.sessionID = sessionID;
224
+ }
225
+ static async startAsLeader(game, sessionID) {
226
+ await HubLink.call('sideQuest.start', { sessionID, engineVersion: engineVersion() });
227
+ return SharedRunSession.enter(game, sessionID);
228
+ }
229
+ static async joinAsMember(game, sessionID) {
230
+ await HubLink.call('sideQuest.join', { sessionID, engineVersion: engineVersion() });
231
+ return SharedRunSession.enter(game, sessionID);
232
+ }
233
+ static async enter(game, sessionID) {
234
+ const s = new SharedRunSession(game, sessionID);
235
+ await s.subscribe();
236
+ game.remoteSession = s;
237
+ return `The cab hums through streets you don't know yet. Somewhere across the sprawl, the rest of the crew is riding too.\n{cyan-fg}▣ SHARED RUN -- the table is live. Everything you do happens for everyone.{/cyan-fg}`;
238
+ }
239
+ async subscribe() {
240
+ const conn = await HubLink.ready();
241
+ if (!conn)
242
+ throw new Error('offline');
243
+ conn.raw._stream.on('message', (raw) => {
244
+ try {
245
+ const m = JSON.parse(raw);
246
+ if (m.msg === 'added' && m.collection === 'GameSessionEvents' && m.fields?.sessionID === this.sessionID) {
247
+ this.route(m.fields);
248
+ }
249
+ if (m.msg === 'changed' && m.collection === 'GameRunSessions' && m.id === this.sessionID) {
250
+ const status = m.fields?.status;
251
+ if (status === 'interrupted' && !this.over) {
252
+ this.finish(`{yellow-fg}The run dissolves into static -- the link to the table is gone. Everyone keeps their last save.{/yellow-fg}`);
253
+ }
254
+ if (status === 'settled' && !this.over) {
255
+ // The leader settled the table (or the street did) -- ride home.
256
+ void this.homecoming();
257
+ }
258
+ }
259
+ }
260
+ catch { /* not ours */ }
261
+ });
262
+ this.subs.push(await conn.subscribe('sideQuest.session', this.sessionID));
263
+ this.subs.push(await conn.subscribe('sideQuest.events', this.sessionID, 0));
264
+ }
265
+ /** One server event into the panes. seq-deduped: the SDK re-subscribes
266
+ * from 0 after a reconnect and replays what we've already drawn. */
267
+ route(ev) {
268
+ if (ev.seq <= this.lastSeq)
269
+ return;
270
+ this.lastSeq = ev.seq;
271
+ const g = this.game;
272
+ switch (ev.channel) {
273
+ case 'log': {
274
+ for (const line of ev.text.split('\n'))
275
+ g.logBox?.pushLine(line);
276
+ g.followLog?.();
277
+ break;
278
+ }
279
+ case 'meta': {
280
+ for (const line of ev.text.split('\n'))
281
+ g.metaBox?.pushLine(line);
282
+ g.metaBox?.scrollTo(g.metaBox.getScrollHeight());
283
+ break;
284
+ }
285
+ case 'status': {
286
+ // The server resolves visibility -- a status event that reaches
287
+ // this subscription is OURS.
288
+ g.statusBox?.setContent(ev.text);
289
+ break;
290
+ }
291
+ case 'system': {
292
+ for (const line of ev.text.split('\n'))
293
+ g.logBox?.pushLine(`{cyan-fg}${line}{/cyan-fg}`);
294
+ g.followLog?.();
295
+ if (ev.kind === 'death' && ev.data?.player === g.player.name) {
296
+ this.dead = true;
297
+ // Full permadeath (ruling 4): the server already burned the
298
+ // cloud save; close() burns the local one and freezes input --
299
+ // the same one death choke point solo play uses.
300
+ void g.close().then(() => {
301
+ Logger.getInstance().logWithColor(`💀 GAME OVER: ${g.player.name} died on a shared run. The street keeps the change.`, 'red');
302
+ Logger.getInstance().logWithColor(`Press ctrl-c to quit.`, 'red');
303
+ });
304
+ }
305
+ if (ev.kind === 'settled' && !this.over) {
306
+ void this.homecoming();
307
+ }
308
+ break;
309
+ }
310
+ }
311
+ g.screenRender?.();
312
+ }
313
+ /** Typed input, shipped to the table. Returns what handleInput would. */
314
+ async command(input) {
315
+ if (this.dead) {
316
+ return `You're gone. The street keeps the change. (ctrl-c to quit.)`;
317
+ }
318
+ if (this.over)
319
+ return '';
320
+ const verb = input.trim().split(' ')[0]?.toLowerCase();
321
+ if (this.quitArmed) {
322
+ this.quitArmed = false;
323
+ if (/^(y|yes|quit|exit|leave)$/i.test(verb ?? '')) {
324
+ return this.leave();
325
+ }
326
+ // fall through: the answer was a real command.
327
+ }
328
+ else if (verb === 'quit' || verb === 'exit' || verb === 'leave') {
329
+ this.quitArmed = true;
330
+ return `Walk out on a LIVE run? Your snapshot is kept, your share of the wrap-up is not. ("y" to leave -- anything else keeps playing.)`;
331
+ }
332
+ if (!verb)
333
+ return '';
334
+ // THE RIDE HOME: on a shared run the taxi is the settlement
335
+ // handshake, not an engine verb -- the leader closes the table for
336
+ // everyone (snapshots persist, shares already on each stick); a
337
+ // member's cab is a voluntary extraction (kept snapshot, forfeited
338
+ // wrap-up share).
339
+ if (/^call\s+(a\s+|the\s+)?(taxi|cab)\b/i.test(input.trim())) {
340
+ try {
341
+ await HubLink.call('sideQuest.settle', { sessionID: this.sessionID });
342
+ await this.homecoming();
343
+ return '';
344
+ }
345
+ catch (err) {
346
+ const e = err;
347
+ if (e.error === 'not-leader') {
348
+ return this.leave();
349
+ }
350
+ if (e.error === 'bad-status' || e.error === 'interrupted') {
351
+ await this.homecoming();
352
+ return '';
353
+ }
354
+ return `{yellow-fg}The dispatcher can't find the table -- try again.{/yellow-fg}`;
355
+ }
356
+ }
357
+ try {
358
+ const res = await HubLink.call('sideQuest.command', {
359
+ sessionID: this.sessionID,
360
+ input,
361
+ });
362
+ this.game.lastResolvedVerb = res.verb ?? verb ?? '';
363
+ return res.text;
364
+ }
365
+ catch (err) {
366
+ const e = err;
367
+ if (e.error === 'interrupted' || e.error === 'bad-status') {
368
+ this.finish(`{yellow-fg}${e.reason ?? 'The run is over.'}{/yellow-fg}`);
369
+ return '';
370
+ }
371
+ return `{yellow-fg}The link chokes on that (${e.reason ?? e.message ?? 'no reply'}) -- try again.{/yellow-fg}`;
372
+ }
373
+ }
374
+ /** Voluntary extraction: snapshot written back server-side, wrap-up
375
+ * share forfeited. */
376
+ async leave() {
377
+ try {
378
+ await HubLink.call('sideQuest.leave', { sessionID: this.sessionID });
379
+ }
380
+ catch { /* the server sweep will settle it */ }
381
+ await this.homecoming();
382
+ return `You pull out of the run. The crew's voices fade off the link.`;
383
+ }
384
+ /** The ride home: fresh cloud save (the run's loot, pay, and karma --
385
+ * written back by the server) lands in the live hub player and on
386
+ * disk; the hub Game, which never went anywhere, takes back over. */
387
+ async homecoming() {
388
+ if (this.over)
389
+ return;
390
+ this.finish('');
391
+ const g = this.game;
392
+ const slug = saveSlug(g.player.name);
393
+ try {
394
+ const cloud = await fetchSave(slug);
395
+ if (cloud) {
396
+ restorePlayer(g.player, cloud.player);
397
+ if (g.saveFilePath)
398
+ writeSaveAtomic(g.saveFilePath, cloud);
399
+ }
400
+ }
401
+ catch (err) {
402
+ Logger.getInstance().write(`shared-run: homecoming save pull failed (${err?.message}) -- next cloud sync reconciles.`);
403
+ }
404
+ Logger.getInstance().logWithColor(`\nA cab noses out of the dark and takes you home. The job is settled -- whatever landed on your stick rode home with you.`, 'green');
405
+ g.updateStatus();
406
+ }
407
+ finish(banner) {
408
+ this.over = true;
409
+ this.game.remoteSession = undefined;
410
+ for (const s of this.subs.splice(0)) {
411
+ try {
412
+ s.stop();
413
+ }
414
+ catch { /* already down */ }
415
+ }
416
+ if (banner) {
417
+ for (const line of banner.split('\n'))
418
+ this.game.logBox?.pushLine(line);
419
+ this.game.followLog?.();
420
+ this.game.screenRender?.();
421
+ }
422
+ }
423
+ }
424
+ //# sourceMappingURL=shared-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-run.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/shared-run.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ Command.create({
14
14
  }
15
15
  catch (e) {
16
16
  console.error(e);
17
- process.exit(0);
17
+ process.exit(1);
18
18
  }
19
19
  }, GetCommand);
20
20
  //# sourceMappingURL=global.sub.cmd.js.map
@@ -25,7 +25,7 @@ Command.create({
25
25
  }
26
26
  catch (e) {
27
27
  console.error(e);
28
- process.exit(0);
28
+ process.exit(1);
29
29
  }
30
30
  });
31
31
  //# sourceMappingURL=murder.js.map
@@ -90,7 +90,7 @@ Command.create({
90
90
  }
91
91
  catch (e) {
92
92
  console.error(e);
93
- process.exit(0);
93
+ process.exit(1);
94
94
  }
95
95
  }, RemoteCommand);
96
96
  //# sourceMappingURL=reconfig.sub.cmd.js.map
@@ -177,7 +177,7 @@ Command.create({
177
177
  }
178
178
  catch (e) {
179
179
  console.error(e);
180
- process.exit(0);
180
+ process.exit(1);
181
181
  }
182
182
  }, SetCommand);
183
183
  //# sourceMappingURL=global.sub.cmd.js.map
@@ -98,7 +98,7 @@ Command.create({
98
98
  }
99
99
  catch (e) {
100
100
  console.error(e);
101
- process.exit(0);
101
+ process.exit(1);
102
102
  }
103
103
  });
104
104
  //# sourceMappingURL=ssl.js.map
@@ -122,7 +122,7 @@ Command.create({
122
122
  }
123
123
  catch (e) {
124
124
  console.error(e);
125
- process.exit(0);
125
+ process.exit(1);
126
126
  }
127
127
  }, TestCommand);
128
128
  //# sourceMappingURL=mocha.sub.cmd.js.map
@@ -55,7 +55,7 @@ const Version = Command.create({
55
55
  }
56
56
  catch (e) {
57
57
  console.error(e);
58
- process.exit(0);
58
+ process.exit(1);
59
59
  }
60
60
  });
61
61
  export default Version;
@@ -358,7 +358,13 @@ export class MPI {
358
358
  catch {
359
359
  Log.error(`This project's version is at ${projectRelease}, however you are using ${systemRelease}.`);
360
360
  Log.notice(`Consider updating this project, or installing the version of Meteor using 'maka install meteor --release ${projectRelease}'`);
361
- process.exit(0);
361
+ // Exit NONZERO: this is a failure, and callers (especially CI
362
+ // pipelines running `maka build` under `bash -e`) must see it
363
+ // as one. This used to exit 0, which let a real deploy
364
+ // pipeline sail past a build that never produced a bundle --
365
+ // with a stale build/ artifact lying around it would have
366
+ // shipped old code silently.
367
+ process.exit(1);
362
368
  }
363
369
  }
364
370
  Log.notice(`Running: meteor ${runArgs.join(' ')}`);
@@ -771,19 +777,18 @@ export class MPI {
771
777
  return String(value);
772
778
  }
773
779
  };
774
- sdk.on('log', ({ level, args }) => {
780
+ sdk.on('log', ({ args }) => {
775
781
  const line = args.map((a) => (typeof a === 'string' ? a : safeStringify(a))).join(' ');
776
- // The SDK's console tap emits an event for every Console call
777
- // *before* the original method's own level check runs, so debug-
778
- // level chatter the tool's Console itself suppresses at default
779
- // verbosity (tropohouse download notes, "Doing HTTP request",
780
- // ...) still arrives here. Match upstream `meteor run`: keep it
781
- // out of the console, but keep it in the log file, where the
782
- // extra detail is useful.
783
- if (level !== 'debug') {
784
- process.stdout.write(line + '\n'); // console: no timestamps
785
- }
786
- writeLog(line); // log file: with timestamps
782
+ // Log file ONLY -- never the console. The SDK's console tap
783
+ // emits an event for every Console call and then still runs the
784
+ // original method, which already prints every non-debug level to
785
+ // the terminal itself (only debug is suppressed at default
786
+ // verbosity). Printing here too double-printed every app/tool
787
+ // line -- easy to miss because Console's copy is wrapped/
788
+ // prefixed while this raw copy isn't, so the two rarely compared
789
+ // equal; app stderr lines (raw passthrough on both paths) made
790
+ // it visible. The file still gets everything, debug included.
791
+ writeLog(line);
787
792
  });
788
793
  await handle.start();
789
794
  Log.success(`Running: http://localhost:${options.port}`);