@volter/supercode-teams 0.2.157 → 0.2.158

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 (2) hide show
  1. package/package.json +1 -1
  2. package/terminal-mail.mjs +22 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.2.157",
3
+ "version": "0.2.158",
4
4
  "type": "module",
5
5
  "description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
6
6
  "license": "MIT",
package/terminal-mail.mjs CHANGED
@@ -14,6 +14,7 @@ function confirmed(batch) {
14
14
  let offset = batch.offset, buffered = '';
15
15
  const decoder = new StringDecoder('utf8');
16
16
  const bytes = Buffer.alloc(64 * 1024);
17
+ let matched = 0, fragments = 0;
17
18
  for (;;) {
18
19
  const count = readSync(fd, bytes, 0, bytes.length, offset);
19
20
  if (!count) return false;
@@ -24,7 +25,22 @@ function confirmed(batch) {
24
25
  let row; try { row = JSON.parse(line); } catch { continue; }
25
26
  const content = batch.kind === 'codex' && row.type === 'response_item' && row.payload?.type === 'message' && row.payload.role === 'user'
26
27
  ? row.payload.content : batch.kind === 'grok' && row.type === 'user' ? row.content : null;
27
- if (textOf(content) === batch.text) return true;
28
+ const text = textOf(content);
29
+ if (text === null || text.length === 0) continue;
30
+ if (text === batch.text) return { fragments: 1 };
31
+ // Older mail delivery omitted the paste delimiter, so terminal newlines
32
+ // submitted one envelope as several native user messages. Recover only
33
+ // exact, ordered fragments of the retained bytes, separated by original
34
+ // newlines. Never infer delivery from an id, substring or empty composer.
35
+ let next = matched;
36
+ while (next < batch.text.length && batch.text[next] === '\n') next++;
37
+ if (matched && batch.text.startsWith(text, next)) {
38
+ matched = next + text.length; fragments++;
39
+ } else if (batch.text.startsWith(text)) {
40
+ matched = text.length; fragments = 1;
41
+ } else { matched = 0; fragments = 0; }
42
+ if (matched === batch.text.length) return { fragments };
43
+
28
44
  }
29
45
  }
30
46
  } finally { closeSync(fd); }
@@ -50,7 +66,7 @@ export class TerminalMailbox {
50
66
  const delivered = ids.every(id => this.state.receipts.some(r => r.message_ids.includes(id)));
51
67
  const batch = this.state.active;
52
68
  return { delivered, queued: !delivered, message_ids: ids,
53
- ...(delivered ? { receipt: 'native-user-message' } : { reason: batch?.error ?? 'queued', batch: batch?.id ?? null }) };
69
+ ...(delivered ? { receipt: this.state.receipts.some(r => r.receipt === 'native-user-messages' && r.message_ids.some(id => ids.includes(id))) ? 'native-user-messages' : 'native-user-message' } : { reason: batch?.error ?? 'queued', batch: batch?.id ?? null }) };
54
70
  }
55
71
  enqueue(text, ids, identity, host, session) {
56
72
  const messageIds = ids?.length ? ids : [`input-${randomUUID()}`];
@@ -95,7 +111,7 @@ export class TerminalMailbox {
95
111
  if (!batch) return;
96
112
  const seen = batch.offset !== null ? confirmed(batch) : (await this.load(batch.locator, { message_offset: batch.messageOffset, message_limit: 1000 })).session?.messages?.some(message => message.role === 'user' && textOf(message.content) === batch.text);
97
113
  if (seen) {
98
- const receipt = { batch: batch.id, message_ids: batch.message_ids, delivered: true, receipt: 'native-user-message', at: Date.now() };
114
+ const receipt = { batch: batch.id, message_ids: batch.message_ids, delivered: true, receipt: seen.fragments > 1 ? 'native-user-messages' : 'native-user-message', fragments: seen.fragments ?? 1, at: Date.now() };
99
115
  appendFileSync(join(this.dir, 'receipts.jsonl'), JSON.stringify(receipt) + '\n', { mode: 0o600 });
100
116
  this.state.receipts.push(receipt);
101
117
  this.state.active = null; this.save(); this.log(receipt); return;
@@ -104,7 +120,9 @@ export class TerminalMailbox {
104
120
  // Persist uncertainty before I/O. A daemon restart checks the transcript;
105
121
  // it never guesses that an unacknowledged paste did not happen.
106
122
  batch.phase = 'paste_started'; this.save();
107
- await this.host.sendInput(this.session.id, batch.text, { submitMode: 'none' });
123
+ // The terminal host's final newline selects one bracketed paste;
124
+ // submitMode:none holds the separate Enter until the paste completes.
125
+ await this.host.sendInput(this.session.id, `${batch.text}\n`, { submitMode: 'none' });
108
126
  batch.phase = 'pasted'; this.save();
109
127
  }
110
128
  if (batch.phase === 'paste_started') {