@astrosheep/square 0.3.70 → 0.3.72
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/activity-feed.d.ts +4 -5
- package/dist/activity-feed.js +14 -10
- package/dist/artifact.d.ts +26 -33
- package/dist/artifact.js +346 -317
- package/dist/attention-presentation.js +2 -9
- package/dist/automatic-session.js +6 -6
- package/dist/boundary-presentation.js +3 -3
- package/dist/catch-decisions.d.ts +19 -12
- package/dist/catch-decisions.js +32 -68
- package/dist/claude-delivery.js +7 -7
- package/dist/claude-mod.js +18 -7
- package/dist/cli/catch-presentation.d.ts +7 -0
- package/dist/cli/catch-presentation.js +55 -0
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +5 -23
- package/dist/cli/express-presentation.d.ts +10 -0
- package/dist/cli/express-presentation.js +196 -0
- package/dist/cli/maintenance-commands.d.ts +4 -0
- package/dist/cli/maintenance-commands.js +29 -6
- package/dist/cli/observation-commands.d.ts +7 -5
- package/dist/cli/observation-commands.js +275 -262
- package/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +43 -56
- package/dist/cli/registry.js +2 -1
- package/dist/cli/square-commands.d.ts +3 -9
- package/dist/cli/square-commands.js +134 -255
- package/dist/codex-queue.js +4 -1
- package/dist/decisions.d.ts +26 -74
- package/dist/decisions.js +190 -335
- package/dist/delivery-health.js +13 -22
- package/dist/delivery-operations.d.ts +0 -11
- package/dist/delivery-operations.js +44 -33
- package/dist/delivery.d.ts +33 -32
- package/dist/delivery.js +70 -81
- package/dist/help.js +6 -1
- package/dist/inbox.d.ts +27 -0
- package/dist/inbox.js +55 -18
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/list.d.ts +7 -1
- package/dist/list.js +49 -122
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +7 -37
- package/dist/model.d.ts +4 -44
- package/dist/model.js +1 -3
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +13 -7
- package/dist/open-square.d.ts +16 -2
- package/dist/open-square.js +40 -1
- package/dist/packages/agent-delivery/src/claude.d.ts +2 -11
- package/dist/packages/agent-delivery/src/index.d.ts +2 -42
- package/dist/packages/agent-delivery/src/opencode.d.ts +2 -11
- package/dist/packages/agent-delivery/src/paseo.d.ts +2 -13
- package/dist/packages/agent-delivery/src/pi-client.d.ts +2 -9
- package/dist/packages/agent-delivery/src/types.d.ts +42 -0
- package/dist/participant-host.d.ts +6 -3
- package/dist/participant-host.js +44 -38
- package/dist/perception-projection.d.ts +6 -15
- package/dist/perception-projection.js +6 -26
- package/dist/plugins/opencode/delivery.js +9 -9
- package/dist/plugins/opencode/index.js +3 -3
- package/dist/ports.d.ts +156 -11
- package/dist/presentation-operations.d.ts +1 -1
- package/dist/presentation-operations.js +35 -44
- package/dist/presentation.d.ts +12 -19
- package/dist/presentation.js +33 -54
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +1 -1
- package/dist/routes.d.ts +7 -14
- package/dist/routes.js +34 -72
- package/dist/runtime.d.ts +12 -39
- package/dist/runtime.js +33 -164
- package/dist/square-actions.d.ts +11 -21
- package/dist/square-actions.js +171 -275
- package/dist/square-application.d.ts +31 -55
- package/dist/square-application.js +625 -141
- package/dist/square-core.d.ts +3 -94
- package/dist/square-core.js +8 -353
- package/dist/square-domain.d.ts +24 -0
- package/dist/square-domain.js +77 -0
- package/dist/square-facade.d.ts +360 -9
- package/dist/square-migration.d.ts +24 -0
- package/dist/square-migration.js +211 -0
- package/dist/square-projections.d.ts +2 -42
- package/dist/square-projections.js +1 -37
- package/dist/square-sqlite.d.ts +59 -0
- package/dist/square-sqlite.js +702 -0
- package/dist/stream.d.ts +3 -10
- package/dist/stream.js +81 -52
- package/dist/views.d.ts +27 -95
- package/dist/views.js +217 -87
- package/dist/wake-eligibility.d.ts +15 -5
- package/dist/wake-eligibility.js +32 -16
- package/dist/wakes.d.ts +3 -3
- package/dist/wakes.js +31 -27
- package/guides/application-facade-delivery-evidence.md +200 -0
- package/guides/application-facade-design.md +95 -0
- package/guides/change-waits.md +4 -4
- package/guides/migration.md +77 -0
- package/guides/postcommit-simplification-performance.md +36 -0
- package/guides/primitive-catch-consolidation.md +85 -0
- package/guides/primitive-history-consolidation.md +76 -0
- package/guides/primitive-status-consolidation.md +87 -0
- package/guides/primitive-storage-consolidation.md +128 -0
- package/guides/row-runtime-delivery-evidence.md +160 -0
- package/guides/row-storage-design.md +567 -0
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/delivery.ts +11 -11
- package/plugins/opencode/index.ts +3 -3
- package/plugins/paseo/client/square-message.tsx +77 -64
- package/plugins/paseo/shared/message.ts +16 -0
- package/plugins/pi/square-pi.js +5 -1
- package/dist/activity.d.ts +0 -14
- package/dist/activity.js +0 -248
- package/dist/square-file-adapter.d.ts +0 -26
- package/dist/square-file-adapter.js +0 -85
- package/dist/square-state.d.ts +0 -6
- package/dist/square-state.js +0 -138
- package/dist/square-storage.d.ts +0 -14
- package/dist/square-storage.js +0 -188
- package/dist/square-wiring.d.ts +0 -33
- package/dist/square-wiring.js +0 -109
- package/dist/watch.d.ts +0 -8
- package/dist/watch.js +0 -252
|
@@ -1,27 +1,15 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { once } from 'node:events';
|
|
1
3
|
import { runClaudeMod } from '../claude-mod.js';
|
|
2
4
|
import { runCodexHookAsync } from '../codex-hook.js';
|
|
3
|
-
import {
|
|
4
|
-
import { sweepPendingNotifications } from '../notifications.js';
|
|
5
|
-
import { cmdListSquares } from '../list.js';
|
|
6
|
-
import { nameKey, parseActivityId, sameName } from '../model.js';
|
|
5
|
+
import { isSquareError, sameName } from '../model.js';
|
|
7
6
|
import { commandPrefix, participantIdentity, renderGrepActivitiesView, renderEventCli, renderAmbientEventFacts, renderPresenceAnchor, truncateChars, withPathOutput, quoteShell, } from '../presentation.js';
|
|
8
|
-
import { actId, nowMs } from '../runtime.js';
|
|
9
7
|
import { style } from '../tty-style.js';
|
|
10
|
-
import { cmdStream, cmdStreamNdjson } from '../stream.js';
|
|
11
8
|
import { formatRelativeTime, formatTimestamp, parseTimeOrRelative } from '../time.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { createSquareApplication } from '../square-application.js';
|
|
16
|
-
import { historyPresentation } from '../views.js';
|
|
17
|
-
import { hostLedgerForEnv } from '../registry.js';
|
|
18
|
-
import { fail, parseBoundedLimit, parseDurationMs, parseNameList, parseNonNegativeInteger, readStdin, requireParticipant, requireSquarePath, requireValue, usage, } from './context.js';
|
|
19
|
-
import { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from '../catch-decisions.js';
|
|
9
|
+
import { formatActivityId, parseActivityId, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from '../square-application.js';
|
|
10
|
+
import { renderCatchOutcome, renderCatchProgress } from './catch-presentation.js';
|
|
11
|
+
import { applicationFor as application, fail, parseBoundedLimit, parseDurationMs, parseNameList, parseNonNegativeInteger, readStdin, requireSquarePath, requireValue, usage, } from './context.js';
|
|
20
12
|
const STATUS_PARTICIPANT_PREVIEW_LIMIT = 10;
|
|
21
|
-
/** A participant counts as here when their last sign of life sits inside this window. */
|
|
22
|
-
const STATUS_HERE_WINDOW_MS = 30 * 60_000;
|
|
23
|
-
const HISTORY_DEFAULT_LIMIT = 10;
|
|
24
|
-
const HISTORY_MAX_LIMIT = 100;
|
|
25
13
|
const PARTICIPANTS_DEFAULT_LIMIT = 20;
|
|
26
14
|
const PARTICIPANTS_MAX_LIMIT = 100;
|
|
27
15
|
const INBOX_DEFAULT_LIMIT = 20;
|
|
@@ -31,12 +19,71 @@ function inboxDisplay(value) {
|
|
|
31
19
|
const truncated = truncateChars(value, INBOX_DISPLAY_CHARS - 1);
|
|
32
20
|
return truncated.remaining === 0 ? truncated.text : `${truncated.text}…`;
|
|
33
21
|
}
|
|
22
|
+
function renderSquareList(data, projection) {
|
|
23
|
+
const { items, stopped, remaining, next } = data;
|
|
24
|
+
if (data.total === 0) {
|
|
25
|
+
return ['(no squares found)', ...(stopped ? [style('dim', '○ the walk stopped early — deeper squares may still be hiding')] : [])].join('\n') + '\n';
|
|
26
|
+
}
|
|
27
|
+
const lines = ['squares'];
|
|
28
|
+
for (const item of items) {
|
|
29
|
+
const glyph = item.activities > 0 ? '●' : style('dim', '○');
|
|
30
|
+
lines.push(`${glyph} ${inboxDisplay(item.path)}${style('dim', ` · ${formatRelativeTime(item.lastActiveAt, projection.now)} · ${item.participants.length} in the square · ${item.activities} ${item.activities === 1 ? 'activity' : 'activities'}`)}`);
|
|
31
|
+
const context = item.context.slice(0, 2);
|
|
32
|
+
if (context.length === 0)
|
|
33
|
+
lines.push(` ${style('dim', 'context')} · (none)`);
|
|
34
|
+
else {
|
|
35
|
+
context.forEach((line, index) => lines.push(` ${index === 0 ? style('dim', 'context') : ' '} · ${inboxDisplay(line)}`));
|
|
36
|
+
const hidden = item.context.length - context.length;
|
|
37
|
+
if (hidden > 0)
|
|
38
|
+
lines.push(style('dim', ` · … ${hidden} more ${hidden === 1 ? 'line' : 'lines'}`));
|
|
39
|
+
}
|
|
40
|
+
const participants = item.participants.slice(0, 3);
|
|
41
|
+
const hidden = item.participants.length - participants.length;
|
|
42
|
+
const names = participants.length === 0 ? 'nobody' : participants.map((name) => participantIdentity(inboxDisplay(name))).join(' · ');
|
|
43
|
+
lines.push(` ${style('dim', 'participants')} · ${names}${hidden > 0 ? style('dim', ` · … ${hidden} more`) : ''}`);
|
|
44
|
+
}
|
|
45
|
+
if (remaining > 0) {
|
|
46
|
+
lines.push(style('dim', stopped ? ' … more squares' : ` … ${remaining} more ${remaining === 1 ? 'square' : 'squares'}`));
|
|
47
|
+
if (next !== undefined)
|
|
48
|
+
lines.push(`square list --depth ${projection.depth} --limit ${projection.limit} --after ${quoteShell(next)}`);
|
|
49
|
+
}
|
|
50
|
+
if (stopped)
|
|
51
|
+
lines.push(style('dim', '○ the walk stopped early — deeper squares may still be hiding'));
|
|
52
|
+
return lines.join('\n') + '\n';
|
|
53
|
+
}
|
|
34
54
|
export const listCommand = {
|
|
35
|
-
parse
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
parse(argv, context) {
|
|
56
|
+
let depth = DEFAULT_LIST_DEPTH;
|
|
57
|
+
let limit = DEFAULT_LIST_LIMIT;
|
|
58
|
+
let after;
|
|
59
|
+
for (let index = 0; index < argv.length; index += 2) {
|
|
60
|
+
const flag = argv[index], value = argv[index + 1];
|
|
61
|
+
if (value === undefined || !['--depth', '--limit', '--after'].includes(flag))
|
|
62
|
+
usage(context.command);
|
|
63
|
+
if (flag === '--after') {
|
|
64
|
+
if (after !== undefined || value.length === 0 || path.isAbsolute(value))
|
|
65
|
+
usage(context.command);
|
|
66
|
+
after = value;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (!/^\d+$/.test(value))
|
|
70
|
+
usage(context.command);
|
|
71
|
+
const number = Number(value);
|
|
72
|
+
if (!Number.isSafeInteger(number) || (flag === '--depth' ? number > MAX_LIST_DEPTH : number === 0 || number > MAX_LIST_LIMIT))
|
|
73
|
+
usage(context.command);
|
|
74
|
+
if (flag === '--depth')
|
|
75
|
+
depth = number;
|
|
76
|
+
else
|
|
77
|
+
limit = number;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { depth, limit, after };
|
|
38
81
|
},
|
|
39
|
-
|
|
82
|
+
async execute(intent, context) {
|
|
83
|
+
const outcome = await application(context).discover(intent);
|
|
84
|
+
return renderSquareList(outcome.data, outcome.projection);
|
|
85
|
+
},
|
|
86
|
+
present: (result) => process.stdout.write(result),
|
|
40
87
|
};
|
|
41
88
|
export const streamCommand = {
|
|
42
89
|
parse(argv, context) {
|
|
@@ -76,17 +123,39 @@ export const streamCommand = {
|
|
|
76
123
|
},
|
|
77
124
|
async execute(intent, context) {
|
|
78
125
|
const squarePath = requireSquarePath(context);
|
|
79
|
-
if (intent.ndjson)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
126
|
+
if (!intent.ndjson) {
|
|
127
|
+
process.stderr.write(`✕ interactive stream was removed\nsquare --location ${quoteShell(path.resolve(context.cwd, squarePath))} stream --ndjson\n`);
|
|
128
|
+
process.exitCode = 2;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const controller = new AbortController();
|
|
132
|
+
const interrupt = () => controller.abort();
|
|
133
|
+
process.once('SIGINT', interrupt);
|
|
134
|
+
try {
|
|
135
|
+
for await (const record of application(context).stream({ recipient: intent.forName, start: intent.start }, { signal: controller.signal })) {
|
|
136
|
+
if (!process.stdout.write(`${JSON.stringify(record)}\n`))
|
|
137
|
+
await once(process.stdout, 'drain', { signal: controller.signal });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (controller.signal.aborted)
|
|
142
|
+
process.exitCode = 130;
|
|
143
|
+
else if (isSquareError(error) && error.code === 'unavailable') {
|
|
144
|
+
process.stderr.write(`square not found: ${squarePath}\n`);
|
|
145
|
+
process.exitCode = 2;
|
|
146
|
+
}
|
|
147
|
+
else
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
process.off('SIGINT', interrupt);
|
|
152
|
+
}
|
|
83
153
|
},
|
|
84
154
|
present: () => { },
|
|
85
155
|
};
|
|
86
156
|
export const catchCommand = {
|
|
87
157
|
parse(argv, context) {
|
|
88
|
-
|
|
89
|
-
let idleMs;
|
|
158
|
+
let idle;
|
|
90
159
|
let mention;
|
|
91
160
|
let limit;
|
|
92
161
|
let id;
|
|
@@ -108,11 +177,11 @@ export const catchCommand = {
|
|
|
108
177
|
index += 1;
|
|
109
178
|
}
|
|
110
179
|
else if (argv[index] === '--idle') {
|
|
111
|
-
|
|
180
|
+
idle = parseDurationMs(requireValue(argv, index, argv[index]), argv[index]);
|
|
112
181
|
index += 1;
|
|
113
182
|
}
|
|
114
183
|
else if (argv[index] === '--mention') {
|
|
115
|
-
mention =
|
|
184
|
+
mention = true;
|
|
116
185
|
}
|
|
117
186
|
else if (argv[index] === '--limit') {
|
|
118
187
|
limit = parseBoundedLimit(argv[index + 1], '--limit', CATCH_MAX_LIMIT, `${commandPrefix(requireSquarePath(context))} catch --limit ${CATCH_MAX_LIMIT}`);
|
|
@@ -129,29 +198,47 @@ export const catchCommand = {
|
|
|
129
198
|
if (argv.some((flag) => ['--idle', '--from', '--mention', '--limit', '--replace'].includes(flag))) {
|
|
130
199
|
fail('✕ --id cannot be combined with --idle, --from, --mention, --limit or --replace\nsquare catch --help');
|
|
131
200
|
}
|
|
132
|
-
return { id
|
|
201
|
+
return { id };
|
|
133
202
|
}
|
|
134
|
-
if (
|
|
203
|
+
if (idle !== undefined && now)
|
|
135
204
|
fail('catch accepts --now or --idle, not both.');
|
|
136
|
-
|
|
137
|
-
if (idleMs === undefined)
|
|
138
|
-
now = true;
|
|
139
|
-
if (replace && now)
|
|
205
|
+
if (replace && idle === undefined)
|
|
140
206
|
fail('--replace can only be used with --idle.');
|
|
141
207
|
return {
|
|
142
|
-
...(participants.length > 0 ? { participants } : {}),
|
|
208
|
+
...(participants.length > 0 ? { from: participants } : {}),
|
|
143
209
|
...(mention === undefined ? {} : { mention }),
|
|
144
210
|
limit: limit ?? CATCH_DEFAULT_LIMIT,
|
|
145
|
-
...(
|
|
211
|
+
...(idle === undefined ? {} : { idle }),
|
|
146
212
|
...(replace ? { replace } : {}),
|
|
147
|
-
...(now ? { now } : {}),
|
|
148
213
|
};
|
|
149
214
|
},
|
|
150
215
|
async execute(intent, context) {
|
|
151
216
|
const squarePath = requireSquarePath(context);
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
217
|
+
const controller = new AbortController();
|
|
218
|
+
const interrupt = () => controller.abort();
|
|
219
|
+
process.once('SIGINT', interrupt);
|
|
220
|
+
try {
|
|
221
|
+
const outcome = await application(context).catch(intent, {
|
|
222
|
+
signal: controller.signal,
|
|
223
|
+
onProgress(progress) {
|
|
224
|
+
const line = renderCatchProgress(squarePath, progress);
|
|
225
|
+
if (line !== undefined)
|
|
226
|
+
process.stderr.write(line);
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
const rendered = renderCatchOutcome(squarePath, outcome, intent);
|
|
230
|
+
process.stdout.write(rendered.stdout);
|
|
231
|
+
process.exitCode = rendered.exitCode;
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (!controller.signal.aborted)
|
|
235
|
+
throw error;
|
|
236
|
+
process.stdout.write(withPathOutput(squarePath, '○ you step back — catch stopped'));
|
|
237
|
+
process.exitCode = 130;
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
process.off('SIGINT', interrupt);
|
|
241
|
+
}
|
|
155
242
|
},
|
|
156
243
|
present: () => { },
|
|
157
244
|
};
|
|
@@ -161,8 +248,8 @@ function parseActRef(value, flag) {
|
|
|
161
248
|
fail(`Invalid ${flag}: expected an activity id like act/12`);
|
|
162
249
|
return index;
|
|
163
250
|
}
|
|
164
|
-
function parseTimestamp(value, flag) {
|
|
165
|
-
const timestamp = parseTimeOrRelative(value,
|
|
251
|
+
function parseTimestamp(value, flag, now) {
|
|
252
|
+
const timestamp = parseTimeOrRelative(value, now);
|
|
166
253
|
if (!Number.isFinite(timestamp))
|
|
167
254
|
fail(`Invalid ${flag} timestamp: ${value}`);
|
|
168
255
|
return timestamp;
|
|
@@ -188,12 +275,11 @@ function historyContinuationArgs(argv) {
|
|
|
188
275
|
}
|
|
189
276
|
function parseHistory(argv, context) {
|
|
190
277
|
const squarePath = requireSquarePath(context);
|
|
191
|
-
let
|
|
192
|
-
let
|
|
278
|
+
let limit;
|
|
279
|
+
let since;
|
|
193
280
|
let after;
|
|
194
|
-
let
|
|
195
|
-
|
|
196
|
-
const atIndexes = [];
|
|
281
|
+
let before;
|
|
282
|
+
const at = [];
|
|
197
283
|
let beforeContext;
|
|
198
284
|
let afterContext;
|
|
199
285
|
let mention;
|
|
@@ -207,8 +293,7 @@ function parseHistory(argv, context) {
|
|
|
207
293
|
for (let index = 0; index < argv.length; index++) {
|
|
208
294
|
const flag = argv[index];
|
|
209
295
|
if (flag === '--limit') {
|
|
210
|
-
|
|
211
|
-
lastNExplicit = true;
|
|
296
|
+
limit = parseBoundedLimit(argv[index + 1], '--limit', HISTORY_MAX_LIMIT, `${commandPrefix(squarePath)} history --limit ${HISTORY_MAX_LIMIT}`);
|
|
212
297
|
index += 1;
|
|
213
298
|
}
|
|
214
299
|
else if (flag === '--from') {
|
|
@@ -216,22 +301,22 @@ function parseHistory(argv, context) {
|
|
|
216
301
|
index += 1;
|
|
217
302
|
}
|
|
218
303
|
else if (flag === '--since') {
|
|
219
|
-
|
|
304
|
+
since = parseTimestamp(requireValue(argv, index, flag), flag, application(context).now());
|
|
220
305
|
index += 1;
|
|
221
306
|
}
|
|
222
307
|
else if (flag === '--after') {
|
|
223
|
-
|
|
308
|
+
after = formatActivityId(parseActRef(requireValue(argv, index, flag), flag));
|
|
224
309
|
index += 1;
|
|
225
310
|
}
|
|
226
311
|
else if (flag === '--before') {
|
|
227
|
-
|
|
312
|
+
before = formatActivityId(parseActRef(requireValue(argv, index, flag), flag));
|
|
228
313
|
index += 1;
|
|
229
314
|
}
|
|
230
315
|
else if (flag === '--at') {
|
|
231
316
|
const values = requireValue(argv, index, flag).split(',');
|
|
232
317
|
if (values.some((value) => value === ''))
|
|
233
318
|
fail(`Invalid ${flag}: expected an activity id like act/12`);
|
|
234
|
-
|
|
319
|
+
at.push(...values.map((value) => formatActivityId(parseActRef(value, flag))));
|
|
235
320
|
index += 1;
|
|
236
321
|
}
|
|
237
322
|
else if (flag === '-B') {
|
|
@@ -282,26 +367,12 @@ function parseHistory(argv, context) {
|
|
|
282
367
|
fail('--grep and --fixed cannot be combined.');
|
|
283
368
|
if (grep === '' || fixed === '')
|
|
284
369
|
fail('--grep and --fixed require non-empty text.');
|
|
285
|
-
if (
|
|
370
|
+
if (before !== undefined && after !== undefined)
|
|
286
371
|
fail('--before and --after cannot be combined.');
|
|
287
|
-
if (!lastNExplicit && atIndexes.length > 0)
|
|
288
|
-
lastN = null;
|
|
289
372
|
return {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
afterIndex,
|
|
294
|
-
beforeIndex,
|
|
295
|
-
atIndexes: atIndexes.length === 0 ? undefined : atIndexes,
|
|
296
|
-
beforeContext,
|
|
297
|
-
afterContext,
|
|
298
|
-
mention,
|
|
299
|
-
noTruncate,
|
|
300
|
-
grep,
|
|
301
|
-
fixed,
|
|
302
|
-
order,
|
|
303
|
-
format,
|
|
304
|
-
json,
|
|
373
|
+
query: { limit, from: participants, since, after, before, at: at.length === 0 ? undefined : at,
|
|
374
|
+
contextBefore: beforeContext, contextAfter: afterContext, mention, grep, fixed, order },
|
|
375
|
+
noTruncate, format, json,
|
|
305
376
|
continuationArgs: historyContinuationArgs(argv),
|
|
306
377
|
};
|
|
307
378
|
}
|
|
@@ -309,14 +380,10 @@ function historyContinuationCommand(options, squarePath, args) {
|
|
|
309
380
|
const full = [...(options.continuationArgs ?? []), ...args];
|
|
310
381
|
return `${commandPrefix(squarePath)} history ${full.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
|
|
311
382
|
}
|
|
312
|
-
/** The archive-visible activity model: content plus the lifecycle moves that keep its story honest — a raised hand pairs with its lowering, and a departure pairs with the return. */
|
|
313
|
-
function isArchiveActivity(item) {
|
|
314
|
-
return item.kind === 'say' || item.kind === 'done' || item.kind === 'hold' || item.kind === 'resume' || item.kind === 'join';
|
|
315
|
-
}
|
|
316
383
|
function renderFields(sayNumbers, item, fields) {
|
|
317
384
|
return fields.map((field) => {
|
|
318
385
|
switch (field) {
|
|
319
|
-
case 'id': return
|
|
386
|
+
case 'id': return formatActivityId(item.index);
|
|
320
387
|
case 'author':
|
|
321
388
|
case 'actor': return item.actor ?? '';
|
|
322
389
|
case 'ts':
|
|
@@ -324,7 +391,7 @@ function renderFields(sayNumbers, item, fields) {
|
|
|
324
391
|
case 'kind': return item.kind;
|
|
325
392
|
case 'body': return 'body' in item && typeof item.body === 'string' ? item.body.replace(/\s+/g, ' ').trim() : '';
|
|
326
393
|
case 'number': return item.kind === 'say' ? String(sayNumbers[item.index]) : '';
|
|
327
|
-
case 'reply': return item.kind === 'say' && item.reply !== undefined ?
|
|
394
|
+
case 'reply': return item.kind === 'say' && item.reply !== undefined ? formatActivityId(item.reply) : '';
|
|
328
395
|
default: return '';
|
|
329
396
|
}
|
|
330
397
|
}).join('\t');
|
|
@@ -332,7 +399,7 @@ function renderFields(sayNumbers, item, fields) {
|
|
|
332
399
|
function jsonLine(sayNumbers, item) {
|
|
333
400
|
const act = item;
|
|
334
401
|
return JSON.stringify({
|
|
335
|
-
id:
|
|
402
|
+
id: formatActivityId(item.index),
|
|
336
403
|
index: item.index,
|
|
337
404
|
kind: act.kind,
|
|
338
405
|
author: act.actor ?? null,
|
|
@@ -342,11 +409,11 @@ function jsonLine(sayNumbers, item) {
|
|
|
342
409
|
number: act.kind === 'say' ? sayNumbers[act.index] : null,
|
|
343
410
|
mentions: act.kind === 'say' ? [...(act.mentions ?? [])] : [],
|
|
344
411
|
reach: act.kind === 'say' ? act.reach ?? null : null,
|
|
345
|
-
reply: act.kind === 'say' && act.reply !== undefined ?
|
|
412
|
+
reply: act.kind === 'say' && act.reply !== undefined ? formatActivityId(act.reply) : null,
|
|
346
413
|
});
|
|
347
414
|
}
|
|
348
415
|
function renderHistoryProjection(projection, visible, noTruncate, squarePath) {
|
|
349
|
-
const shown = visible
|
|
416
|
+
const shown = visible;
|
|
350
417
|
const preview = noTruncate || shown.length <= 1 ? undefined : 200;
|
|
351
418
|
const chunks = [];
|
|
352
419
|
// Presence anchors collect into one closing line instead of interrupting the page.
|
|
@@ -377,51 +444,30 @@ export const historyCommand = {
|
|
|
377
444
|
parse(argv, context) { return parseHistory(argv, context); },
|
|
378
445
|
async execute(options, context) {
|
|
379
446
|
const squarePath = requireSquarePath(context);
|
|
380
|
-
|
|
447
|
+
let outcome;
|
|
381
448
|
try {
|
|
382
|
-
|
|
383
|
-
// then --order only changes how the selected page is displayed. The
|
|
384
|
-
// plain archive hides `read` bookkeeping, while --at/-C/--since windows
|
|
385
|
-
// render the raw activity stream around their coordinates.
|
|
386
|
-
const projection = await historyPresentation(square, { ...options, order: 'asc' });
|
|
387
|
-
const hideReadActs = options.atIndexes === undefined && options.beforeContext === undefined && options.afterContext === undefined && options.after === undefined;
|
|
388
|
-
let events = hideReadActs ? projection.activities.filter((activity) => activity.kind !== 'read') : [...projection.activities];
|
|
389
|
-
if (options.lastN === null && events.length > HISTORY_MAX_LIMIT) {
|
|
390
|
-
fail(`✕ history is capped at ${HISTORY_MAX_LIMIT} activities\n${historyContinuationCommand(options, squarePath, ['--limit', String(HISTORY_MAX_LIMIT)])}`);
|
|
391
|
-
}
|
|
392
|
-
const searching = options.grep !== undefined || options.fixed !== undefined;
|
|
393
|
-
const totalMatches = searching ? events.length : 0;
|
|
394
|
-
if (options.lastN != null) {
|
|
395
|
-
events = options.afterIndex !== undefined
|
|
396
|
-
? events.slice(0, options.lastN)
|
|
397
|
-
: events.slice(-options.lastN);
|
|
398
|
-
}
|
|
399
|
-
if (options.order === 'desc')
|
|
400
|
-
events.reverse();
|
|
401
|
-
if (options.json)
|
|
402
|
-
return events.map((item) => jsonLine(projection.sayNumbers, item)).join('\n') + (events.length > 0 ? '\n' : '');
|
|
403
|
-
if (options.format !== undefined && options.format.length > 0) {
|
|
404
|
-
return events.map((item) => renderFields(projection.sayNumbers, item, options.format)).join('\n') + (events.length > 0 ? '\n' : '');
|
|
405
|
-
}
|
|
406
|
-
const pattern = options.grep ?? options.fixed;
|
|
407
|
-
const output = pattern === undefined || pattern === ''
|
|
408
|
-
? renderHistoryProjection(projection, events, options.noTruncate === true, squarePath)
|
|
409
|
-
: renderGrepActivitiesView(events, totalMatches, options.noTruncate, squarePath, pattern, options.fixed !== undefined, () => 'full');
|
|
410
|
-
const publicEvents = events.filter(isArchiveActivity);
|
|
411
|
-
const allPublic = projection.activities.filter(isArchiveActivity);
|
|
412
|
-
const pageMin = publicEvents.length === 0 ? undefined : Math.min(...publicEvents.map((item) => item.index));
|
|
413
|
-
const pageMax = publicEvents.length === 0 ? undefined : Math.max(...publicEvents.map((item) => item.index));
|
|
414
|
-
const hasMore = options.lastN != null && publicEvents.length > 0 && (options.afterIndex !== undefined
|
|
415
|
-
? allPublic.some((item) => item.index > (pageMax ?? options.afterIndex))
|
|
416
|
-
: allPublic.some((item) => item.index < (pageMin ?? Infinity)));
|
|
417
|
-
const cursorDirection = options.afterIndex !== undefined ? '--after' : '--before';
|
|
418
|
-
const cursorIndex = cursorDirection === '--after' ? Math.max(...publicEvents.map((item) => item.index)) : Math.min(...publicEvents.map((item) => item.index));
|
|
419
|
-
const continuation = hasMore ? `\n\n${historyContinuationCommand(options, squarePath, [cursorDirection, actId(cursorIndex), '--limit', String(options.lastN ?? HISTORY_DEFAULT_LIMIT)])}` : '';
|
|
420
|
-
return withPathOutput(squarePath, output + continuation, { participantCount: projection.participantCount });
|
|
449
|
+
outcome = await application(context).history(options.query);
|
|
421
450
|
}
|
|
422
|
-
|
|
423
|
-
|
|
451
|
+
catch (error) {
|
|
452
|
+
const bounds = error?.operation?.historyBounds;
|
|
453
|
+
if (bounds !== undefined)
|
|
454
|
+
fail(`✕ history is capped at ${bounds.maxLimit} activities\n${historyContinuationCommand(options, squarePath, ['--limit', String(bounds.maxLimit)])}`);
|
|
455
|
+
throw error;
|
|
424
456
|
}
|
|
457
|
+
const projection = outcome.projection;
|
|
458
|
+
const events = projection.activities;
|
|
459
|
+
if (options.json)
|
|
460
|
+
return events.map((item) => jsonLine(projection.sayNumbers, item)).join('\n') + (events.length > 0 ? '\n' : '');
|
|
461
|
+
if (options.format !== undefined && options.format.length > 0) {
|
|
462
|
+
return events.map((item) => renderFields(projection.sayNumbers, item, options.format)).join('\n') + (events.length > 0 ? '\n' : '');
|
|
463
|
+
}
|
|
464
|
+
const pattern = options.query.grep ?? options.query.fixed;
|
|
465
|
+
const output = pattern === undefined || pattern === ''
|
|
466
|
+
? renderHistoryProjection(projection, projection.visibleActivities, options.noTruncate, squarePath)
|
|
467
|
+
: renderGrepActivitiesView(projection.visibleActivities, projection.totalMatches, options.noTruncate, squarePath, pattern, options.query.fixed !== undefined, () => 'full');
|
|
468
|
+
const next = projection.continuation;
|
|
469
|
+
const continuation = next === undefined ? '' : `\n\n${historyContinuationCommand(options, squarePath, [`--${next.direction}`, next.cursor, '--limit', String(next.limit)])}`;
|
|
470
|
+
return withPathOutput(squarePath, output + continuation, { participantCount: projection.standingCount });
|
|
425
471
|
},
|
|
426
472
|
present: (result) => process.stdout.write(result),
|
|
427
473
|
};
|
|
@@ -442,30 +488,26 @@ export const participantsCommand = {
|
|
|
442
488
|
parse(argv, context) { return parseParticipants(argv, context); },
|
|
443
489
|
async execute(intent, context) {
|
|
444
490
|
const squarePath = requireSquarePath(context);
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
? [
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
return withPathOutput(squarePath, ['participants', ...lines, ...tail].join('\n'), {
|
|
466
|
-
participantCount,
|
|
467
|
-
});
|
|
468
|
-
}
|
|
491
|
+
const { data, projection } = await application(context).participants();
|
|
492
|
+
const now = projection.now;
|
|
493
|
+
const participants = data.participants;
|
|
494
|
+
const lines = participants.slice(0, intent.limit).map((participant) => {
|
|
495
|
+
const glyph = participant.state === 'done' ? '○' : participant.presence === 'watching' ? '◎' : participant.activityCount > 0 && projection.classificationByName[participant.name] === 'here' ? '●' : '○';
|
|
496
|
+
const state = participant.state === 'done' ? 'done' : participant.presence === 'watching' ? 'catching' : participant.state;
|
|
497
|
+
const last = participant.lastActiveAt === undefined ? '—' : formatRelativeTime(participant.lastActiveAt, now);
|
|
498
|
+
return ` ${glyph} ${participant.name}${style('dim', ` · ${state} · ${participant.activityCount} ${participant.activityCount === 1 ? 'activity' : 'activities'} · ${last}`)}`;
|
|
499
|
+
});
|
|
500
|
+
const tail = participants.length <= intent.limit
|
|
501
|
+
? []
|
|
502
|
+
: [
|
|
503
|
+
style('dim', ` ○ ${lines.length} of ${participants.length} participants shown`),
|
|
504
|
+
...(participants.length <= PARTICIPANTS_MAX_LIMIT ? [
|
|
505
|
+
`${participantsLimitCommand(squarePath, participants.length)}`,
|
|
506
|
+
] : []),
|
|
507
|
+
];
|
|
508
|
+
return withPathOutput(squarePath, ['participants', ...lines, ...tail].join('\n'), {
|
|
509
|
+
participantCount: projection.standingCount,
|
|
510
|
+
});
|
|
469
511
|
},
|
|
470
512
|
present: (result) => process.stdout.write(result),
|
|
471
513
|
};
|
|
@@ -474,100 +516,88 @@ export const statusCommand = {
|
|
|
474
516
|
usage(context.command); return undefined; },
|
|
475
517
|
async execute(_intent, context) {
|
|
476
518
|
const squarePath = requireSquarePath(context);
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
? '
|
|
502
|
-
: participant.
|
|
503
|
-
?
|
|
504
|
-
:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
: participant.unreadActivityCount > 0
|
|
511
|
-
? `${participant.unreadActivityCount} change${participant.unreadActivityCount === 1 ? '' : 's'} waiting`
|
|
512
|
-
: 'caught up';
|
|
513
|
-
return ` ${glyph} ${participantIdentity(participant.name)}${style('dim', ` ${summary}${attention === '' ? '' : ` · ${attention}`}`)}`;
|
|
514
|
-
}));
|
|
515
|
-
const unshown = Math.max(0, orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT) + lingering;
|
|
516
|
-
if (orderedHere.length > STATUS_PARTICIPANT_PREVIEW_LIMIT) {
|
|
517
|
-
people.push(` ○ … ${orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT} more here`);
|
|
518
|
-
}
|
|
519
|
-
if (lingering > 0)
|
|
520
|
-
people.push(` ○ … ${lingering} lingering`);
|
|
521
|
-
if (unshown > 0) {
|
|
522
|
-
people.push(`${result.participants.length <= PARTICIPANTS_MAX_LIMIT
|
|
523
|
-
? participantsLimitCommand(squarePath, result.participants.length)
|
|
524
|
-
: `${commandPrefix(squarePath)} participants`}`);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
const cap = result.hardCap === null ? 'unlimited' : `${result.hardCap} each`;
|
|
528
|
-
const holdTime = result.holdAt === undefined ? 'just now' : formatRelativeTime(result.holdAt, result.now);
|
|
529
|
-
const hold = result.holdActive
|
|
530
|
-
? `· ${result.holdActor === undefined ? 'someone' : participantIdentity(result.holdActor)} raised a hand${result.holdReason ? ` — ${result.holdReason}` : ''}${style('dim', ` · ${holdTime}`)}`
|
|
531
|
-
: undefined;
|
|
532
|
-
const visible = result.latestAct === undefined
|
|
533
|
-
? { text: '', bodyClipped: false }
|
|
534
|
-
: renderAmbientEventFacts(result.latestAct, context.name ?? '', {
|
|
535
|
-
now: result.now,
|
|
536
|
-
preview: 200,
|
|
537
|
-
actNumber: presentation.latestActNumber,
|
|
538
|
-
squareState: presentation.state,
|
|
539
|
-
});
|
|
540
|
-
const latest = visible.text === ''
|
|
541
|
-
? [result.latestAct === undefined
|
|
542
|
-
? ' ○ no public activity yet'
|
|
543
|
-
: ' · the latest words were meant for other ears']
|
|
544
|
-
: [` ${visible.text.replace(/\n/g, '\n ')}`];
|
|
545
|
-
// Presence events after the latest public act: otherwise the roster can say someone is
|
|
546
|
-
// here while the latest line shows them leaving, with nothing to reconcile the two.
|
|
547
|
-
const latestIndex = result.latestAct?.index ?? -1;
|
|
548
|
-
const stepsIn = presentation.state.acts.filter((act) => act.kind === 'join' && act.index > latestIndex);
|
|
549
|
-
for (const act of stepsIn.slice(-3)) {
|
|
550
|
-
const rejoined = presentation.state.acts.some((other) => other.kind === 'done' && other.actor === act.actor && other.index < act.index);
|
|
551
|
-
latest.push(style('dim', ` → ${participantIdentity(act.actor)} ${rejoined ? 'stepped back in' : 'stepped in'} · ${formatRelativeTime(act.at, result.now)}`));
|
|
519
|
+
const { data: result, projection: presentation } = await application(context).status(context.name);
|
|
520
|
+
const participantsByName = new Map(result.participants.map((participant) => [participant.name, participant]));
|
|
521
|
+
const orderedHere = presentation.orderedHereNames.map((name) => participantsByName.get(name));
|
|
522
|
+
const lingering = presentation.lingeringCount;
|
|
523
|
+
const people = [];
|
|
524
|
+
if (result.activeCount === 0) {
|
|
525
|
+
people.push(' ○ nobody in the square');
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
if (orderedHere.length === 0)
|
|
529
|
+
people.push(' ○ nobody here right now');
|
|
530
|
+
people.push(...orderedHere.slice(0, STATUS_PARTICIPANT_PREVIEW_LIMIT).map((participant) => {
|
|
531
|
+
const glyph = participant.presence === 'watching'
|
|
532
|
+
? '◎'
|
|
533
|
+
: participant.activityCount > 0 ? '●' : '○';
|
|
534
|
+
const summary = participant.presence === 'watching'
|
|
535
|
+
? 'is nearby · catching'
|
|
536
|
+
: participant.activityCount > 0
|
|
537
|
+
? `is nearby · ${formatRelativeTime(participant.lastActiveAt ?? result.now, result.now)}`
|
|
538
|
+
: `is nearby · quiet · ${participant.lastActiveAt === undefined ? 'just now' : formatRelativeTime(participant.lastActiveAt, result.now)}`;
|
|
539
|
+
const showAttention = presentation.attentionNames.includes(participant.name);
|
|
540
|
+
const attention = !showAttention
|
|
541
|
+
? ''
|
|
542
|
+
: participant.pendingMentionCount > 0
|
|
543
|
+
? `${participant.pendingMentionCount} ${participant.pendingMentionCount === 1 ? 'mention' : 'mentions'} waiting`
|
|
544
|
+
: participant.unreadActivityCount > 0
|
|
545
|
+
? `${participant.unreadActivityCount} change${participant.unreadActivityCount === 1 ? '' : 's'} waiting`
|
|
546
|
+
: 'caught up';
|
|
547
|
+
return ` ${glyph} ${participantIdentity(participant.name)}${style('dim', ` ${summary}${attention === '' ? '' : ` · ${attention}`}`)}`;
|
|
548
|
+
}));
|
|
549
|
+
const unshown = Math.max(0, orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT) + lingering;
|
|
550
|
+
if (orderedHere.length > STATUS_PARTICIPANT_PREVIEW_LIMIT) {
|
|
551
|
+
people.push(` ○ … ${orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT} more here`);
|
|
552
552
|
}
|
|
553
|
-
if (
|
|
554
|
-
|
|
555
|
-
if (
|
|
556
|
-
|
|
553
|
+
if (lingering > 0)
|
|
554
|
+
people.push(` ○ … ${lingering} lingering`);
|
|
555
|
+
if (unshown > 0) {
|
|
556
|
+
people.push(`${presentation.knownParticipantCount <= PARTICIPANTS_MAX_LIMIT
|
|
557
|
+
? participantsLimitCommand(squarePath, presentation.knownParticipantCount)
|
|
558
|
+
: `${commandPrefix(squarePath)} participants`}`);
|
|
557
559
|
}
|
|
558
|
-
const counts = [
|
|
559
|
-
`${here.length} here`,
|
|
560
|
-
...(lingering > 0 ? [`${lingering} lingering`] : []),
|
|
561
|
-
`${result.doneCount} done`,
|
|
562
|
-
`cap ${cap}`,
|
|
563
|
-
`throttle ${result.throttlePerMinute === undefined ? 'none' : `${result.throttlePerMinute}/min`}`,
|
|
564
|
-
].join(' · ');
|
|
565
|
-
const output = [
|
|
566
|
-
style('dim', counts),
|
|
567
|
-
...(hold === undefined ? [] : ['', hold]), '', style('dim', 'around the square'), ...people, '', style('dim', 'latest'), ...latest,
|
|
568
|
-
].join('\n');
|
|
569
|
-
return withPathOutput(squarePath, output, { participantCount: result.activeCount, held: result.holdActive });
|
|
570
560
|
}
|
|
561
|
+
const cap = result.hardCap === null ? 'unlimited' : `${result.hardCap} each`;
|
|
562
|
+
const holdTime = result.hold?.at === undefined ? 'just now' : formatRelativeTime(result.hold.at, result.now);
|
|
563
|
+
const hold = result.hold !== null
|
|
564
|
+
? `· ${result.hold.by === undefined ? 'someone' : participantIdentity(result.hold.by)} raised a hand${result.hold.reason ? ` — ${result.hold.reason}` : ''}${style('dim', ` · ${holdTime}`)}`
|
|
565
|
+
: undefined;
|
|
566
|
+
const visible = result.latestActivity === undefined
|
|
567
|
+
? { text: '', bodyClipped: false }
|
|
568
|
+
: renderAmbientEventFacts(result.latestActivity, presentation.viewer, {
|
|
569
|
+
now: result.now,
|
|
570
|
+
preview: 200,
|
|
571
|
+
actNumber: presentation.latestActNumber,
|
|
572
|
+
perception: presentation.latestPerception,
|
|
573
|
+
});
|
|
574
|
+
const latest = visible.text === ''
|
|
575
|
+
? [result.latestActivity === undefined
|
|
576
|
+
? ' ○ no public activity yet'
|
|
577
|
+
: ' · the latest words were meant for other ears']
|
|
578
|
+
: [` ${visible.text.replace(/\n/g, '\n ')}`];
|
|
579
|
+
// Presence events after the latest public act: otherwise the roster can say someone is
|
|
580
|
+
// here while the latest line shows them leaving, with nothing to reconcile the two.
|
|
581
|
+
for (const { activity, rejoined } of presentation.joins) {
|
|
582
|
+
latest.push(style('dim', ` → ${participantIdentity(activity.actor)} ${rejoined ? 'stepped back in' : 'stepped in'} · ${formatRelativeTime(activity.at, result.now)}`));
|
|
583
|
+
}
|
|
584
|
+
if (presentation.joinCount > 3)
|
|
585
|
+
latest.push(style('dim', ` → … ${presentation.joinCount - 3} more stepped in`));
|
|
586
|
+
if (visible.bodyClipped && result.latestActivity !== undefined) {
|
|
587
|
+
latest.push(`${commandPrefix(squarePath)} history --at ${result.latestActivity.id} -C 2 --no-truncate`);
|
|
588
|
+
}
|
|
589
|
+
const counts = [
|
|
590
|
+
`${orderedHere.length} here`,
|
|
591
|
+
...(lingering > 0 ? [`${lingering} lingering`] : []),
|
|
592
|
+
`${result.doneCount} done`,
|
|
593
|
+
`cap ${cap}`,
|
|
594
|
+
`throttle ${result.throttlePerMinute === undefined ? 'none' : `${result.throttlePerMinute}/min`}`,
|
|
595
|
+
].join(' · ');
|
|
596
|
+
const output = [
|
|
597
|
+
style('dim', counts),
|
|
598
|
+
...(hold === undefined ? [] : ['', hold]), '', style('dim', 'around the square'), ...people, '', style('dim', 'latest'), ...latest,
|
|
599
|
+
].join('\n');
|
|
600
|
+
return withPathOutput(squarePath, output, { participantCount: presentation.standingCount, held: presentation.held });
|
|
571
601
|
},
|
|
572
602
|
present: (result) => process.stdout.write(result),
|
|
573
603
|
};
|
|
@@ -608,35 +638,18 @@ export const inboxCommand = {
|
|
|
608
638
|
: INBOX_DEFAULT_LIMIT;
|
|
609
639
|
return { sessionId, json, limit };
|
|
610
640
|
},
|
|
611
|
-
async execute(intent) {
|
|
612
|
-
const
|
|
613
|
-
const
|
|
614
|
-
if (left.squarePath < right.squarePath)
|
|
615
|
-
return -1;
|
|
616
|
-
if (left.squarePath > right.squarePath)
|
|
617
|
-
return 1;
|
|
618
|
-
const leftName = nameKey(left.name);
|
|
619
|
-
const rightName = nameKey(right.name);
|
|
620
|
-
if (leftName < rightName)
|
|
621
|
-
return -1;
|
|
622
|
-
if (leftName > rightName)
|
|
623
|
-
return 1;
|
|
624
|
-
if (left.name < right.name)
|
|
625
|
-
return -1;
|
|
626
|
-
if (left.name > right.name)
|
|
627
|
-
return 1;
|
|
628
|
-
return 0;
|
|
629
|
-
});
|
|
630
|
-
const rows = ordered.slice(0, intent.limit).map((membership) => ({
|
|
641
|
+
async execute(intent, context) {
|
|
642
|
+
const { data } = await application(context).inbox(intent.sessionId, { limit: intent.limit });
|
|
643
|
+
const rows = data.rows.map((membership) => ({
|
|
631
644
|
namePreview: inboxDisplay(membership.name),
|
|
632
645
|
squarePathPreview: inboxDisplay(membership.squarePath),
|
|
633
|
-
pending: membership.
|
|
646
|
+
pending: membership.pending,
|
|
634
647
|
}));
|
|
635
648
|
if (intent.json)
|
|
636
|
-
return `${JSON.stringify({ rows, total:
|
|
649
|
+
return `${JSON.stringify({ rows, total: data.total })}\n`;
|
|
637
650
|
return [
|
|
638
651
|
...rows.map((row) => `${row.namePreview}\t${row.squarePathPreview}\t${row.pending}\n`),
|
|
639
|
-
...(rows.length <
|
|
652
|
+
...(rows.length < data.total ? [`${rows.length} of ${data.total} memberships shown\n`] : []),
|
|
640
653
|
].join('');
|
|
641
654
|
},
|
|
642
655
|
present: (result) => process.stdout.write(result),
|