@volter/supercode-teams 0.3.99 → 0.3.100
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/machine.mjs +2 -1
- package/mail/send.mjs +25 -5
- package/package.json +1 -1
package/machine.mjs
CHANGED
|
@@ -3419,7 +3419,8 @@ export class TeamsMachine extends MachineCore {
|
|
|
3419
3419
|
case 'harness.v1.mail.handover': {
|
|
3420
3420
|
if (entry.principal !== 'local' || entry.appDoor) throw Object.assign(new Error('mail is handed over here by this machine\'s own processes'), { code: 403 });
|
|
3421
3421
|
if (typeof params.address !== 'string' || typeof params.id !== 'string' || !parseAddress(params.address)) throw Object.assign(new Error('a hand-over names an address and a message id'), { code: 400 });
|
|
3422
|
-
|
|
3422
|
+
// a hand-over is moved to cur/ once delivered whatever `mark_read` says (MailSend.handOver)
|
|
3423
|
+
return this.mailSend.handOver(params.address, params.id, { wake: params.wake === true });
|
|
3423
3424
|
}
|
|
3424
3425
|
// harness serve's `sessions.message` (its mail to a session or an agent, not its `as_user` turn), asked here by
|
|
3425
3426
|
// harness serve itself: one implementation of a send, whatever the entry.
|
package/mail/send.mjs
CHANGED
|
@@ -52,6 +52,7 @@ export class MailSend {
|
|
|
52
52
|
*/
|
|
53
53
|
constructor({ machine, mailRoot, live, store, agents, relays, askMachine, deliverRuntime, codexAnswer, typeTurn, log = () => {} }) {
|
|
54
54
|
Object.assign(this, { machine, mailRoot, live, store, agents, relays, askMachine, deliverRuntime, codexAnswer, typeTurn, log });
|
|
55
|
+
this.handing = new Set(); // `<address>\n<id>` of each hand-over running here (handOver)
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
// ---- one send ----------------------------------------------------------------------------------------------------
|
|
@@ -665,16 +666,27 @@ export class MailSend {
|
|
|
665
666
|
/**
|
|
666
667
|
* A message filed unread in `address`'s mailbox handed to its session's door, once (mail_watch.rs `carry` and message.rs
|
|
667
668
|
* `push`, and the native watch's notices): only a door that hands it to the session (a relay, a runtime) takes it, a
|
|
668
|
-
* hook's is woken when `wake`, and an agent's mail is planned
|
|
669
|
-
*
|
|
669
|
+
* hook's is woken when `wake`, and an agent's mail is planned. One handed over is moved to `cur/` here, whoever asked:
|
|
670
|
+
* its receiver has it, so its next inbox read never shows it again (the carrier marks it read only when its own call
|
|
671
|
+
* answers delivered, which a hand-over past its bound never does). The
|
|
672
|
+
* hand-over is recorded on its wake before it starts, so one interrupted mid-way (its daemon ended) is never handed over
|
|
673
|
+
* again; one still running here, its carrier past its bound, answers 'later' until it settles. Answers
|
|
670
674
|
* `{ outcome: 'delivered' | 'filed' | 'later', detail }`.
|
|
671
675
|
*/
|
|
672
|
-
async handOver(address, id, {
|
|
676
|
+
async handOver(address, id, { wake = false } = {}) {
|
|
673
677
|
const found = this.store.findIn(address, id);
|
|
674
678
|
if (!found) return { outcome: 'filed', detail: 'not in its mailbox' };
|
|
675
679
|
const sent = readJson(found.path);
|
|
676
680
|
if (!sent) return { outcome: 'later', detail: 'its envelope could not be read' };
|
|
677
681
|
if (found.state !== 'unread') return { outcome: 'filed', detail: 'already read' };
|
|
682
|
+
// one already handed to its receiver's door (that delivery's claim, the door's or the carrier's: a daemon that ended
|
|
683
|
+
// between the delivery and moving the copy left it unread) is moved to `cur/`, never handed over again. A reader's
|
|
684
|
+
// claim is not one: a reader that ended before reading put the copy back unread, and it is handed over
|
|
685
|
+
const claim = this.store.claimOf(address, id);
|
|
686
|
+
if (claim?.recipient === true && (claim.via === 'door' || claim.via === 'carrier')) {
|
|
687
|
+
this.store.markRead(address, found.path);
|
|
688
|
+
return { outcome: 'filed', detail: 'already handed over' };
|
|
689
|
+
}
|
|
678
690
|
const parsed = parseAddress(address);
|
|
679
691
|
if (parsed?.harness === AGENT_HARNESS) {
|
|
680
692
|
const plan = await this.#plan(sent, address, {});
|
|
@@ -691,11 +703,18 @@ export class MailSend {
|
|
|
691
703
|
return { outcome: 'filed', detail: `its door is ${door.kind}` };
|
|
692
704
|
}
|
|
693
705
|
const state = this.store.wakeState(address, id);
|
|
706
|
+
// one still running here (its carrier gave up on its answer, past its bound) is waited for: the wake stays and is
|
|
707
|
+
// tried again after its backoff, settled by that hand-over's own outcome
|
|
708
|
+
const key = `${address}\n${id}`;
|
|
709
|
+
if (this.handing.has(key)) return { outcome: 'later', detail: 'its hand-over is still in progress' };
|
|
694
710
|
if (state.handover_at_ms != null) return { outcome: 'filed', detail: 'an earlier hand-over never settled' };
|
|
695
711
|
this.store.setWakeState(address, id, { ...state, handover_at_ms: Date.now() });
|
|
712
|
+
this.handing.add(key);
|
|
696
713
|
try {
|
|
697
|
-
await this.route(sent, address, door, true, false);
|
|
698
|
-
|
|
714
|
+
const how = await this.route(sent, address, door, true, false);
|
|
715
|
+
// handed to the session (or already its): moved to cur/ (one only queued for a runtime not woken would stay unread)
|
|
716
|
+
const now = this.store.findIn(address, id);
|
|
717
|
+
if (how !== 'queued' && now?.state === 'unread') this.store.markRead(address, now.path);
|
|
699
718
|
return { outcome: 'delivered', detail: null };
|
|
700
719
|
} catch (error) {
|
|
701
720
|
// a message its door can never take (too long for a relay) stays filed for the session to read
|
|
@@ -704,6 +723,7 @@ export class MailSend {
|
|
|
704
723
|
if (error.unanswered) return { outcome: 'later', detail: `unanswered: ${error.message}` };
|
|
705
724
|
return error instanceof Refused ? { outcome: 'filed', detail: error.kind } : { outcome: 'later', detail: error.message };
|
|
706
725
|
} finally {
|
|
726
|
+
this.handing.delete(key);
|
|
707
727
|
const after = this.store.wakeState(address, id);
|
|
708
728
|
this.store.setWakeState(address, id, { ...after, handover_at_ms: null });
|
|
709
729
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-teams",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.100",
|
|
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",
|