@astrosheep/square 0.3.11 → 0.3.13

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.
Files changed (127) hide show
  1. package/codex-plugin/.codex-plugin/plugin.json +1 -1
  2. package/codex-plugin/hooks/hooks.json +9 -0
  3. package/dist/activity-feed.d.ts +14 -0
  4. package/dist/activity-feed.js +5 -5
  5. package/dist/activity.d.ts +9 -0
  6. package/dist/activity.js +112 -96
  7. package/dist/artifact.d.ts +20 -0
  8. package/dist/artifact.js +317 -648
  9. package/dist/automatic-session.d.ts +5 -0
  10. package/dist/automatic-session.js +86 -0
  11. package/dist/boundary-presentation.d.ts +5 -0
  12. package/dist/boundary-presentation.js +6 -5
  13. package/dist/claude-hook.d.ts +9 -0
  14. package/dist/claude-hook.js +35 -3
  15. package/dist/cli/context.d.ts +35 -0
  16. package/dist/cli/context.js +26 -31
  17. package/dist/cli/harness-command.d.ts +28 -0
  18. package/dist/cli/harness-command.js +30 -15
  19. package/dist/cli/maintenance-commands.d.ts +7 -0
  20. package/dist/cli/maintenance-commands.js +12 -69
  21. package/dist/cli/meta-commands.d.ts +5 -0
  22. package/dist/cli/observation-commands.d.ts +20 -0
  23. package/dist/cli/observation-commands.js +159 -139
  24. package/dist/cli/program.d.ts +2 -0
  25. package/dist/cli/program.js +3 -12
  26. package/dist/cli/registry.d.ts +9 -0
  27. package/dist/cli/registry.js +2 -4
  28. package/dist/cli/square-commands.d.ts +34 -0
  29. package/dist/cli/square-commands.js +90 -84
  30. package/dist/cmd/notify-once.d.ts +2 -0
  31. package/dist/codex-hook.d.ts +10 -0
  32. package/dist/codex-hook.js +35 -3
  33. package/dist/decisions.d.ts +92 -0
  34. package/dist/decisions.js +93 -81
  35. package/dist/delivery-health.d.ts +21 -0
  36. package/dist/delivery-health.js +41 -34
  37. package/dist/delivery.d.ts +81 -0
  38. package/dist/delivery.js +71 -69
  39. package/dist/file-lock.d.ts +6 -0
  40. package/dist/harness-claude.d.ts +19 -0
  41. package/dist/harness-claude.js +8 -3
  42. package/dist/harness-codex.d.ts +29 -0
  43. package/dist/harness-codex.js +2 -2
  44. package/dist/harness-links.d.ts +17 -0
  45. package/dist/harness-links.js +2 -2
  46. package/dist/harness-pi.d.ts +11 -0
  47. package/dist/harness-pi.js +2 -2
  48. package/dist/harness-stage.d.ts +6 -0
  49. package/dist/harness.d.ts +20 -0
  50. package/dist/harness.js +5 -3
  51. package/dist/help.d.ts +6 -0
  52. package/dist/help.js +12 -13
  53. package/dist/identity.d.ts +13 -0
  54. package/dist/inbox.d.ts +2 -0
  55. package/dist/inbox.js +15 -19
  56. package/dist/index.d.ts +13 -0
  57. package/dist/index.js +31 -67
  58. package/dist/landing.d.ts +10 -0
  59. package/dist/landing.js +95 -0
  60. package/dist/list.d.ts +1 -0
  61. package/dist/list.js +39 -61
  62. package/dist/model.d.ts +147 -0
  63. package/dist/model.js +12 -8
  64. package/dist/notifications.d.ts +30 -0
  65. package/dist/notifications.js +83 -91
  66. package/dist/open-square.d.ts +11 -0
  67. package/dist/open-square.js +4 -0
  68. package/dist/participant-identity.d.ts +1 -0
  69. package/dist/participant-identity.js +3 -0
  70. package/dist/paseo-connection.d.ts +15 -0
  71. package/dist/paseo-delivery.d.ts +14 -0
  72. package/dist/paseo-state.d.ts +11 -0
  73. package/dist/paseo-timeline.d.ts +16 -0
  74. package/dist/presence.d.ts +3 -0
  75. package/dist/presence.js +42 -0
  76. package/dist/presentation.d.ts +91 -0
  77. package/dist/presentation.js +52 -63
  78. package/dist/presented.d.ts +11 -0
  79. package/dist/registry.d.ts +58 -0
  80. package/dist/registry.js +36 -3
  81. package/dist/routes.d.ts +42 -0
  82. package/dist/runtime.d.ts +45 -0
  83. package/dist/runtime.js +48 -55
  84. package/dist/search.d.ts +11 -0
  85. package/dist/square-core.d.ts +111 -0
  86. package/dist/square-core.js +63 -9
  87. package/dist/square-facade.d.ts +86 -0
  88. package/dist/square-facade.js +1 -0
  89. package/dist/square-file-adapter.d.ts +18 -0
  90. package/dist/square-file-adapter.js +70 -0
  91. package/dist/square-storage.d.ts +20 -0
  92. package/dist/square-storage.js +171 -0
  93. package/dist/square-wiring.d.ts +19 -0
  94. package/dist/square-wiring.js +70 -0
  95. package/dist/square.d.ts +2 -0
  96. package/dist/state-cell.d.ts +14 -0
  97. package/dist/state-cell.js +1 -0
  98. package/dist/stream.d.ts +3 -0
  99. package/dist/stream.js +19 -23
  100. package/dist/time.d.ts +6 -0
  101. package/dist/views.d.ts +95 -0
  102. package/dist/views.js +81 -0
  103. package/dist/wake-attempts.d.ts +39 -0
  104. package/dist/wake-attempts.js +8 -4
  105. package/dist/wake-evidence.d.ts +12 -0
  106. package/dist/wake-evidence.js +7 -10
  107. package/dist/wake-port.d.ts +20 -0
  108. package/dist/wake-sink.d.ts +12 -0
  109. package/dist/wakes.d.ts +40 -0
  110. package/dist/wakes.js +62 -0
  111. package/dist/watch.d.ts +2 -0
  112. package/dist/watch.js +89 -210
  113. package/extensions/square-opencode.js +27 -1
  114. package/extensions/square-pi.js +13 -0
  115. package/guides/participant.md +7 -174
  116. package/package.json +5 -4
  117. package/skills/brainstorm/SKILL.md +30 -30
  118. package/skills/square/.claude-plugin/plugin.json +1 -1
  119. package/skills/square/SKILL.md +56 -29
  120. package/skills/square/hooks/hooks.json +9 -0
  121. package/skills/square-feedback/SKILL.md +9 -9
  122. package/dist/compact.js +0 -26
  123. package/dist/doctor.js +0 -36
  124. package/dist/square-application.js +0 -262
  125. package/template.md +0 -4
  126. package/templates/architect.md +0 -4
  127. package/templates/brainstorm.md +0 -4
@@ -1,12 +1,13 @@
1
1
  import { cmdActivity } from '../activity.js';
2
- import { loadSquare } from '../artifact.js';
3
- import { cmdCompact } from '../compact.js';
4
- import { SquareError, formatHardCap, validateName, } from '../model.js';
5
- import { participantCommandPrefix, quoteShell, renderEventCli, renderPublicTail, withPathOutput, } from '../presentation.js';
6
- import { hasAutomaticDeliveryIdentity, localParticipantOwner, recordLocalDone, recordLocalJoin } from '../registry.js';
7
- import { sweepPendingNotifications } from '../notifications.js';
8
- import { inSquareCount, isCurrentlyJoined, nowMs, resolveRosterName } from '../runtime.js';
9
- import { createSquare, execute } from '../square-application.js';
2
+ import { formatActivityId, formatHardCap, parseActivityId, } from '../model.js';
3
+ import { participantCommandPrefix, participantIdentity, renderEventCli, renderAmbientEvent, withPathOutput, } from '../presentation.js';
4
+ import { hasAutomaticDeliveryIdentity, localParticipantOwner, recordLocalDone, recordLocalJoin, } from '../registry.js';
5
+ import { sweepPendingNotifications, wakeNotifierForSquare } from '../notifications.js';
6
+ import { nowMs } from '../runtime.js';
7
+ import { createSquare, openSquare } from '../square-file-adapter.js';
8
+ import { closeOpenSquare } from '../open-square.js';
9
+ import { Square } from '../square-wiring.js';
10
+ import { entryPresentation, eventPresentation } from '../views.js';
10
11
  import { fail, parseHardCap, parsePositiveInteger, readPipedBodyFallback, readStdinSync, requireParticipant, requireValue, resolveBody, usage, } from './context.js';
11
12
  function parseBuild(argv) {
12
13
  const options = { force: false, hardCap: null };
@@ -78,54 +79,55 @@ function parseJoin(argv, context) {
78
79
  export const joinCommand = {
79
80
  parse: parseJoin,
80
81
  async execute(intent, context) {
81
- validateName(intent.name);
82
+ const beforeSquare = await openSquare(context.squarePath, { clock: nowMs });
83
+ const before = await entryPresentation(beforeSquare, intent.name, intent.lastN);
84
+ await closeOpenSquare(beforeSquare);
85
+ const square = await Square.at({ path: context.squarePath, clock: nowMs, notifier: wakeNotifierForSquare(context.squarePath) });
82
86
  try {
83
- const committed = await execute(context.squarePath, { type: 'join', name: intent.name, now: nowMs() });
84
- const joinedName = committed.result.joinedName;
85
- const isRejoin = !committed.result.addParticipant;
86
- const after = loadSquare(context.squarePath);
87
- const preamble = after.preamble.at(-1) === '---' ? after.preamble.slice(0, -1) : after.preamble;
87
+ const participant = await square.join(intent.name);
88
+ const joinedName = participant.name;
89
+ const isRejoin = before.joined;
90
+ const reconnect = isRejoin
91
+ && localParticipantOwner(context.squarePath, joinedName) !== undefined;
92
+ if (isRejoin && !intent.kick && !reconnect) {
93
+ fail([
94
+ `✕ ${participantIdentity(joinedName)} shoos you out of the square`,
95
+ ` · a same-named participant stands here — the name is taken`,
96
+ ` · --kick banishes her and the name becomes yours`,
97
+ `» ${participantCommandPrefix(context.squarePath, joinedName)} join --kick`,
98
+ ].join('\n'));
99
+ }
100
+ const afterSquare = await openSquare(context.squarePath, { clock: nowMs });
101
+ const after = await entryPresentation(afterSquare, joinedName, intent.lastN);
102
+ await closeOpenSquare(afterSquare);
88
103
  recordLocalJoin(joinedName, context.squarePath);
89
104
  await sweepPendingNotifications(context.squarePath);
90
- const activities = renderPublicTail(after.acts, intent.lastN, nowMs(), joinedName);
91
- const contextText = preamble.join('\n').trim();
105
+ const activities = after.recentActivities.map((event) => renderAmbientEvent(event, joinedName, {
106
+ now: nowMs(),
107
+ preview: intent.lastN === null ? undefined : 200,
108
+ actNumber: event.kind === 'say' ? after.sayNumbers[event.index] : undefined,
109
+ })).filter(Boolean).join('\n\n');
110
+ const contextText = after.joinContext;
92
111
  const fallback = hasAutomaticDeliveryIdentity()
93
112
  ? []
94
113
  : ['', `» ${participantCommandPrefix(context.squarePath, joinedName)} catch --idle 30m`, ' no session delivery detected — keep this catch open for new activity'];
114
+ const scene = after.scene;
115
+ const entryLine = !isRejoin
116
+ ? '● You stepped into the square'
117
+ : reconnect && !intent.kick
118
+ ? '● you are already in the square'
119
+ : `✓ you banished the original ${participantIdentity(joinedName)} — the name is yours`;
95
120
  const output = [
96
- `● ${joinedName} stepped into the square`,
121
+ entryLine,
122
+ ...(reconnect || scene === '' ? [] : ['', scene]),
97
123
  ...(isRejoin || contextText === '' ? [] : ['', 'context', contextText]),
98
- ...(activities === '' ? [] : ['', 'recent activity', activities]),
99
- ...(isRejoin ? [] : ['', `» ${participantCommandPrefix(context.squarePath, joinedName)} warmup`]),
124
+ ...(isRejoin || activities === '' ? [] : ['', 'recent activity', activities]),
100
125
  ...fallback,
101
126
  ].join('\n');
102
- return withPathOutput(context.squarePath, output, { participantCount: inSquareCount(after) });
127
+ return withPathOutput(context.squarePath, output, { participantCount: after.participantCount });
103
128
  }
104
- catch (error) {
105
- if (!(error instanceof SquareError) || error.code !== 'conflict')
106
- throw error;
107
- const doc = loadSquare(context.squarePath);
108
- const joinedName = resolveRosterName(doc, intent.name);
109
- if (joinedName === undefined || !isCurrentlyJoined(doc.acts, joinedName))
110
- throw error;
111
- const reconnect = localParticipantOwner(context.squarePath, joinedName) !== undefined;
112
- if (!intent.kick && !reconnect) {
113
- fail([
114
- `✕ ${joinedName} shoos you out of the square`,
115
- ` · a same-named participant stands here — the name is taken`,
116
- ` · --kick banishes her and the name becomes yours`,
117
- `» ${participantCommandPrefix(context.squarePath, joinedName)} join --kick`,
118
- ].join('\n'));
119
- }
120
- recordLocalJoin(joinedName, context.squarePath);
121
- await sweepPendingNotifications(context.squarePath);
122
- const fallback = hasAutomaticDeliveryIdentity()
123
- ? ''
124
- : `\n» ${participantCommandPrefix(context.squarePath, joinedName)} catch --idle 30m\n no session delivery detected — keep this catch open for new activity`;
125
- const line = reconnect && !intent.kick
126
- ? `● you are already in the square`
127
- : `✓ you banished the original ${joinedName} — the name is yours`;
128
- return withPathOutput(context.squarePath, `${line}${fallback}`, { participantCount: inSquareCount(doc) });
129
+ finally {
130
+ await square.close();
129
131
  }
130
132
  },
131
133
  present: (result) => process.stdout.write(result),
@@ -133,7 +135,6 @@ export const joinCommand = {
133
135
  function parseActivity(argv, context) {
134
136
  let force = false;
135
137
  let noWait = false;
136
- let beside;
137
138
  let bell = false;
138
139
  let reply;
139
140
  const bodyArgs = [];
@@ -143,25 +144,21 @@ function parseActivity(argv, context) {
143
144
  force = true;
144
145
  else if (argument === '--no-wait')
145
146
  noWait = true;
146
- else if (argument === '--beside') {
147
- beside = requireValue(argv, index, argument);
148
- index += 1;
149
- }
147
+ else if (argument === '--beside')
148
+ fail('✕ express does not know --beside\n» square express --help');
150
149
  else if (argument === '--bell')
151
150
  bell = true;
152
151
  else if (argument === '--reply') {
153
- const value = requireValue(argv, index, argument).trim().match(/^(?:act_)?(\d+)$/i);
154
- if (!value || !Number.isSafeInteger(Number(value[1])))
155
- fail('Invalid --reply: expected an activity id like act_12 or 12.');
156
- reply = Number(value[1]);
152
+ const replyIndex = parseActivityId(requireValue(argv, index, argument));
153
+ if (replyIndex === undefined)
154
+ fail('Invalid --reply: expected an activity id like act/12');
155
+ reply = replyIndex;
157
156
  index += 1;
158
157
  }
159
158
  else
160
159
  bodyArgs.push(argument);
161
160
  }
162
- if (bell && beside !== undefined)
163
- fail('Invalid express options: --beside and --bell are mutually exclusive.');
164
- const reach = bell ? 'bell' : beside === undefined ? undefined : { beside };
161
+ const reach = bell ? 'bell' : undefined;
165
162
  if (bodyArgs.length !== 1) {
166
163
  if (bodyArgs.length === 0) {
167
164
  const piped = readPipedBodyFallback();
@@ -176,13 +173,13 @@ export const expressCommand = {
176
173
  parse: parseActivity,
177
174
  async execute(intent, context) {
178
175
  await sweepPendingNotifications(context.squarePath);
179
- const reachArg = intent.reach === 'bell' ? ' --bell' : intent.reach === undefined ? '' : ` --beside ${quoteShell(intent.reach.beside)}`;
176
+ const reachArg = intent.reach === 'bell' ? ' --bell' : '';
180
177
  await cmdActivity(context.squarePath, intent.name, intent.activity, resolveBody, {
181
178
  force: intent.force,
182
179
  noWait: intent.noWait,
183
180
  reach: intent.reach,
184
181
  reply: intent.reply,
185
- forceCommand: `${participantCommandPrefix(context.squarePath, intent.name)} express --force${reachArg}${intent.reply === undefined ? '' : ` --reply act_${intent.reply}`} -`,
182
+ forceCommand: `${participantCommandPrefix(context.squarePath, intent.name)} express --force${reachArg}${intent.reply === undefined ? '' : ` --reply ${formatActivityId(intent.reply)}`} -`,
186
183
  });
187
184
  },
188
185
  present: () => { },
@@ -196,10 +193,15 @@ export const doneCommand = {
196
193
  parse: parseDone,
197
194
  async execute(intent, context) {
198
195
  const body = resolveBody(intent.body ?? '').replace(/\r\n/g, '\n').trim();
199
- const committed = await execute(context.squarePath, { type: 'done', name: intent.name, body, now: nowMs() });
200
- const name = committed.acts[0].actor;
196
+ const square = await Square.at({ path: context.squarePath, clock: nowMs, notifier: wakeNotifierForSquare(context.squarePath) });
197
+ const participant = await square.join(intent.name);
198
+ const result = await participant.done(body);
199
+ await square.close();
200
+ const name = result.activity.actor;
201
201
  recordLocalDone(name, context.squarePath);
202
- return withPathOutput(context.squarePath, `× ${name} steps out of the square — done · just now`, { participantCount: inSquareCount(loadSquare(context.squarePath)) });
202
+ const presentation = await openSquare(context.squarePath, { clock: nowMs });
203
+ const participantCount = (await entryPresentation(presentation, name).finally(() => closeOpenSquare(presentation))).participantCount;
204
+ return withPathOutput(context.squarePath, `○ ${participantIdentity(name)} steps out of the square — done · just now`, { participantCount });
203
205
  },
204
206
  present: (result) => process.stdout.write(result),
205
207
  };
@@ -211,9 +213,19 @@ function parseHold(argv, context) {
211
213
  export const holdCommand = {
212
214
  parse: parseHold,
213
215
  async execute(intent, context) {
214
- const committed = await execute(context.squarePath, { type: 'hold', actor: intent.name, body: resolveBody(intent.body ?? '').replace(/\r\n/g, '\n').trim(), now: nowMs() });
215
- const doc = loadSquare(context.squarePath);
216
- return withPathOutput(context.squarePath, renderEventCli(committed.acts[0]), { participantCount: inSquareCount(doc), held: true });
216
+ const square = await Square.at({ path: context.squarePath, clock: nowMs, notifier: wakeNotifierForSquare(context.squarePath) });
217
+ try {
218
+ const participant = await square.join(intent.name);
219
+ const result = await participant.hold(resolveBody(intent.body ?? '').replace(/\r\n/g, '\n').trim());
220
+ await square.close();
221
+ const presentationSquare = await openSquare(context.squarePath, { clock: nowMs });
222
+ const presentation = await eventPresentation(presentationSquare, result.activity.id);
223
+ await closeOpenSquare(presentationSquare);
224
+ return withPathOutput(context.squarePath, renderEventCli(presentation.activity), { participantCount: presentation.participantCount, held: true });
225
+ }
226
+ finally {
227
+ await square.close();
228
+ }
217
229
  },
218
230
  present: (result) => process.stdout.write(result),
219
231
  };
@@ -224,25 +236,19 @@ export const resumeCommand = {
224
236
  return { name: requireParticipant(context.name) };
225
237
  },
226
238
  async execute(intent, context) {
227
- const committed = await execute(context.squarePath, { type: 'resume', actor: intent.name, now: nowMs() });
228
- const doc = loadSquare(context.squarePath);
229
- return withPathOutput(context.squarePath, renderEventCli(committed.acts[0]), { participantCount: inSquareCount(doc) });
230
- },
231
- present: (result) => process.stdout.write(result),
232
- };
233
- export const compactCommand = {
234
- parse(argv, context) {
235
- let keep = 50;
236
- for (let index = 0; index < argv.length; index++) {
237
- if (argv[index] !== '--keep')
238
- usage(context.command);
239
- keep = parsePositiveInteger(requireValue(argv, index, argv[index]), argv[index]);
240
- index += 1;
239
+ const square = await Square.at({ path: context.squarePath, clock: nowMs, notifier: wakeNotifierForSquare(context.squarePath) });
240
+ try {
241
+ const participant = await square.join(intent.name);
242
+ const result = await participant.resume();
243
+ await square.close();
244
+ const presentationSquare = await openSquare(context.squarePath, { clock: nowMs });
245
+ const presentation = await eventPresentation(presentationSquare, result.activity.id);
246
+ await closeOpenSquare(presentationSquare);
247
+ return withPathOutput(context.squarePath, renderEventCli(presentation.activity), { participantCount: presentation.participantCount });
248
+ }
249
+ finally {
250
+ await square.close();
241
251
  }
242
- return { keep };
243
- },
244
- async execute(intent, context) {
245
- await cmdCompact(context.squarePath, intent);
246
252
  },
247
- present: () => { },
253
+ present: (result) => process.stdout.write(result),
248
254
  };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { InboxMembership } from './model.js';
2
+ export interface CodexHookInput {
3
+ session_id?: unknown;
4
+ hook_event_name?: unknown;
5
+ cwd?: unknown;
6
+ source?: unknown;
7
+ }
8
+ export declare function codexHookResponse(input: CodexHookInput, lookup?: (sessionId: string) => Promise<InboxMembership[]> | InboxMembership[], env?: NodeJS.ProcessEnv): Promise<object | undefined>;
9
+ export declare function runCodexHook(inputText: string, env?: NodeJS.ProcessEnv): Promise<string>;
10
+ export declare function runCodexHookAsync(inputText: string, env?: NodeJS.ProcessEnv): Promise<string>;
@@ -1,13 +1,14 @@
1
1
  import { presentPendingAtBoundary } from './boundary-presentation.js';
2
2
  import { sessionInbox } from './inbox.js';
3
- export function codexHookResponse(input, lookup = sessionInbox, env = process.env) {
3
+ import { automaticSessionEnd, automaticSessionStart } from './automatic-session.js';
4
+ export async function codexHookResponse(input, lookup = sessionInbox, env = process.env) {
4
5
  if (typeof input.session_id !== 'string' || input.session_id === '')
5
6
  return undefined;
6
7
  if (input.hook_event_name !== 'PostToolUse')
7
8
  return undefined;
8
9
  return presentPendingAtBoundary(input.session_id, (context) => ({ hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: context } }), lookup, env);
9
10
  }
10
- export function runCodexHook(inputText, env = process.env) {
11
+ export async function runCodexHook(inputText, env = process.env) {
11
12
  let input;
12
13
  try {
13
14
  input = JSON.parse(inputText);
@@ -17,6 +18,37 @@ export function runCodexHook(inputText, env = process.env) {
17
18
  }
18
19
  if (input === null || typeof input !== 'object')
19
20
  return '';
20
- const response = codexHookResponse(input, sessionInbox, env);
21
+ const response = await codexHookResponse(input, sessionInbox, env);
21
22
  return response === undefined ? '' : `${JSON.stringify(response)}\n`;
22
23
  }
24
+ export async function runCodexHookAsync(inputText, env = process.env) {
25
+ let input;
26
+ try {
27
+ input = JSON.parse(inputText);
28
+ }
29
+ catch {
30
+ return '';
31
+ }
32
+ if (input === null || typeof input !== 'object')
33
+ return '';
34
+ const value = input;
35
+ if (typeof value.session_id !== 'string' || typeof value.cwd !== 'string')
36
+ return runCodexHook(inputText, env);
37
+ if (value.hook_event_name === 'SessionStart' || value.hook_event_name === 'SessionResume') {
38
+ try {
39
+ const context = await automaticSessionStart('codex', value.session_id, value.cwd, env);
40
+ return context === undefined ? '' : `${JSON.stringify({ hookSpecificOutput: { hookEventName: value.hook_event_name, additionalContext: context } })}\n`;
41
+ }
42
+ catch {
43
+ return '';
44
+ }
45
+ }
46
+ if (value.hook_event_name === 'SessionEnd') {
47
+ try {
48
+ await automaticSessionEnd('codex', value.session_id, value.cwd, env);
49
+ }
50
+ catch { /* end remains bounded */ }
51
+ return '';
52
+ }
53
+ return runCodexHook(inputText, env);
54
+ }
@@ -0,0 +1,92 @@
1
+ import { type ActivitiesOptions, type Act, type StoredAct, type SquareState, type Reach, type HardCap } from './model.js';
2
+ import { peerPublicActs, peerRoomChanges } from './activity-feed.js';
3
+ export interface UnreadActivitySummary {
4
+ name: string;
5
+ count: number;
6
+ latestActivityAgeMs: number;
7
+ previews: UnreadActivityPreview[];
8
+ }
9
+ export interface UnreadActivityPreview {
10
+ number: number;
11
+ act: Extract<StoredAct, {
12
+ kind: 'say';
13
+ }>;
14
+ }
15
+ export declare function resolveKnownName(squareState: SquareState, name: string): string;
16
+ export interface DecideJoinResult {
17
+ joinedName: string;
18
+ addParticipant: boolean;
19
+ joinAct?: Extract<Act, {
20
+ kind: 'join';
21
+ }>;
22
+ }
23
+ export declare function decideJoin(squareState: SquareState, name: string, now: number): DecideJoinResult;
24
+ export type ActDecision = {
25
+ type: 'sent';
26
+ act: Act;
27
+ confirmation: string;
28
+ ownActCount: number;
29
+ pendingPublic: ReturnType<typeof peerPublicActs>;
30
+ pendingRoomChanges: ReturnType<typeof peerRoomChanges>;
31
+ } | {
32
+ type: 'blocked';
33
+ activitySummaries: UnreadActivitySummary[];
34
+ unreadRoomChanges: ReturnType<typeof peerRoomChanges>;
35
+ } | {
36
+ type: 'capped';
37
+ count: number;
38
+ hardCap: number;
39
+ } | {
40
+ type: 'throttled';
41
+ delayMs: number;
42
+ } | {
43
+ type: 'held';
44
+ reason: string | undefined;
45
+ } | {
46
+ type: 'bell_quota';
47
+ nextAt: number;
48
+ };
49
+ export declare function decideAct(squareState: SquareState, input: {
50
+ name: string;
51
+ body: string;
52
+ force: boolean;
53
+ now: number;
54
+ reach?: Reach;
55
+ reply?: number;
56
+ }): ActDecision;
57
+ export declare function coreDone(squareState: SquareState, name: string, body: string, now: number): Extract<Act, {
58
+ kind: 'done';
59
+ }>;
60
+ export declare function coreHold(squareState: SquareState, actor: string, body: string, now: number): Extract<Act, {
61
+ kind: 'hold';
62
+ }>;
63
+ export declare function coreResume(squareState: SquareState, actor: string, now: number): Extract<Act, {
64
+ kind: 'resume';
65
+ }>;
66
+ export interface ParticipantStatus {
67
+ name: string;
68
+ state: 'active' | 'done' | 'not joined';
69
+ activityCount: number;
70
+ lastActiveAt: number | undefined;
71
+ presence: CorePresenceState;
72
+ presenceAt: number | undefined;
73
+ unreadActivityCount: number;
74
+ pendingMentionCount: number;
75
+ }
76
+ export type CorePresenceState = 'never-joined' | 'active' | 'watching' | 'done';
77
+ export interface StatusResult {
78
+ hardCap: HardCap;
79
+ throttlePerMinute: number | undefined;
80
+ activeCount: number;
81
+ doneCount: number;
82
+ holdActive: boolean;
83
+ holdReason: string | undefined;
84
+ holdActor: string | undefined;
85
+ holdAt: number | undefined;
86
+ participants: ParticipantStatus[];
87
+ latestAct: StoredAct | undefined;
88
+ now: number;
89
+ }
90
+ export declare function coreStatus(squareState: SquareState, now: number): StatusResult;
91
+ export declare function coreParticipants(squareState: SquareState, now: number): ParticipantStatus[];
92
+ export declare function coreActivities(squareState: SquareState, opts: ActivitiesOptions): StoredAct[];