@animalabs/agent-framework 0.32.0 → 0.34.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.
- package/README.md +340 -22
- package/dist/src/admission/admit.d.ts +18 -0
- package/dist/src/admission/admit.d.ts.map +1 -1
- package/dist/src/admission/admit.js +16 -3
- package/dist/src/admission/admit.js.map +1 -1
- package/dist/src/agent.d.ts +208 -80
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +345 -113
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts.map +1 -1
- package/dist/src/api/mcp-server-core.js +50 -12
- package/dist/src/api/mcp-server-core.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +4 -20
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/append-all.d.ts +5 -0
- package/dist/src/append-all.d.ts.map +1 -0
- package/dist/src/append-all.js +8 -0
- package/dist/src/append-all.js.map +1 -0
- package/dist/src/code-execution/isolate/scripts.d.ts +12 -8
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +24 -0
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/config-checks.d.ts +7 -0
- package/dist/src/config-checks.d.ts.map +1 -1
- package/dist/src/config-checks.js +14 -0
- package/dist/src/config-checks.js.map +1 -1
- package/dist/src/context-manager-errors.d.ts +25 -0
- package/dist/src/context-manager-errors.d.ts.map +1 -0
- package/dist/src/context-manager-errors.js +31 -0
- package/dist/src/context-manager-errors.js.map +1 -0
- package/dist/src/context-options.d.ts +70 -0
- package/dist/src/context-options.d.ts.map +1 -0
- package/dist/src/context-options.js +90 -0
- package/dist/src/context-options.js.map +1 -0
- package/dist/src/cut-off-round.js +4 -4
- package/dist/src/deferred-import.d.ts +93 -0
- package/dist/src/deferred-import.d.ts.map +1 -0
- package/dist/src/deferred-import.js +177 -0
- package/dist/src/deferred-import.js.map +1 -0
- package/dist/src/dendrite/audience.d.ts +223 -0
- package/dist/src/dendrite/audience.d.ts.map +1 -0
- package/dist/src/dendrite/audience.js +202 -0
- package/dist/src/dendrite/audience.js.map +1 -0
- package/dist/src/dendrite/index.d.ts +5 -3
- package/dist/src/dendrite/index.d.ts.map +1 -1
- package/dist/src/dendrite/index.js +2 -1
- package/dist/src/dendrite/index.js.map +1 -1
- package/dist/src/dendrite/presets.d.ts +10 -5
- package/dist/src/dendrite/presets.d.ts.map +1 -1
- package/dist/src/dendrite/presets.js +17 -5
- package/dist/src/dendrite/presets.js.map +1 -1
- package/dist/src/dendrite/registry.d.ts +62 -7
- package/dist/src/dendrite/registry.d.ts.map +1 -1
- package/dist/src/dendrite/registry.js +183 -12
- package/dist/src/dendrite/registry.js.map +1 -1
- package/dist/src/dendrite/types.d.ts +91 -8
- package/dist/src/dendrite/types.d.ts.map +1 -1
- package/dist/src/failure-text.d.ts +36 -0
- package/dist/src/failure-text.d.ts.map +1 -0
- package/dist/src/failure-text.js +89 -0
- package/dist/src/failure-text.js.map +1 -0
- package/dist/src/foreign-rounds.d.ts +69 -0
- package/dist/src/foreign-rounds.d.ts.map +1 -0
- package/dist/src/foreign-rounds.js +152 -0
- package/dist/src/foreign-rounds.js.map +1 -0
- package/dist/src/framework.d.ts +2064 -842
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +8586 -3739
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +125 -21
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +487 -72
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/index.d.ts +1 -1
- package/dist/src/gate/index.d.ts.map +1 -1
- package/dist/src/gate/index.js.map +1 -1
- package/dist/src/gate/reply-judge.d.ts +4 -0
- package/dist/src/gate/reply-judge.d.ts.map +1 -1
- package/dist/src/gate/reply-judge.js +12 -3
- package/dist/src/gate/reply-judge.js.map +1 -1
- package/dist/src/gate/rule-scope.d.ts +30 -0
- package/dist/src/gate/rule-scope.d.ts.map +1 -0
- package/dist/src/gate/rule-scope.js +41 -0
- package/dist/src/gate/rule-scope.js.map +1 -0
- package/dist/src/gate/suppress-script-worker.d.ts +2 -0
- package/dist/src/gate/suppress-script-worker.d.ts.map +1 -0
- package/dist/src/gate/suppress-script-worker.js +103 -0
- package/dist/src/gate/suppress-script-worker.js.map +1 -0
- package/dist/src/gate/suppress-scripts.d.ts +105 -0
- package/dist/src/gate/suppress-scripts.d.ts.map +1 -0
- package/dist/src/gate/suppress-scripts.js +403 -0
- package/dist/src/gate/suppress-scripts.js.map +1 -0
- package/dist/src/gate/suppression-review.d.ts +143 -0
- package/dist/src/gate/suppression-review.d.ts.map +1 -0
- package/dist/src/gate/suppression-review.js +463 -0
- package/dist/src/gate/suppression-review.js.map +1 -0
- package/dist/src/gate/suppression-stats.d.ts +125 -0
- package/dist/src/gate/suppression-stats.d.ts.map +1 -0
- package/dist/src/gate/suppression-stats.js +214 -0
- package/dist/src/gate/suppression-stats.js.map +1 -0
- package/dist/src/gate/types.d.ts +142 -7
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/gate/wake-onboarding.d.ts +119 -0
- package/dist/src/gate/wake-onboarding.d.ts.map +1 -0
- package/dist/src/gate/wake-onboarding.js +277 -0
- package/dist/src/gate/wake-onboarding.js.map +1 -0
- package/dist/src/heartbeat/heartbeat.js +1 -1
- package/dist/src/heartbeat/heartbeat.js.map +1 -1
- package/dist/src/held-writes.d.ts +31 -23
- package/dist/src/held-writes.d.ts.map +1 -1
- package/dist/src/held-writes.js +44 -59
- package/dist/src/held-writes.js.map +1 -1
- package/dist/src/index.d.ts +6 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/inference-bounds.d.ts +2 -1
- package/dist/src/inference-bounds.d.ts.map +1 -1
- package/dist/src/inference-bounds.js +9 -6
- package/dist/src/inference-bounds.js.map +1 -1
- package/dist/src/jsonrpc-envelope.d.ts +69 -0
- package/dist/src/jsonrpc-envelope.d.ts.map +1 -0
- package/dist/src/jsonrpc-envelope.js +66 -0
- package/dist/src/jsonrpc-envelope.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +188 -28
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +426 -70
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts +2 -4
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts +2 -4
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +2 -1
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +2 -1
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +6 -6
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +109 -15
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
- package/dist/src/mcpl/modern-connection.js +593 -86
- package/dist/src/mcpl/modern-connection.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts +3 -1
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +15 -9
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +132 -22
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +105 -15
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +9 -7
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +50 -28
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +165 -72
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.js +3 -0
- package/dist/src/mcpl/tool-classes.js.map +1 -1
- package/dist/src/mcpl/tool-presence.d.ts.map +1 -1
- package/dist/src/mcpl/tool-presence.js +10 -6
- package/dist/src/mcpl/tool-presence.js.map +1 -1
- package/dist/src/mcpl/toolset-host.d.ts.map +1 -1
- package/dist/src/mcpl/toolset-host.js +7 -6
- package/dist/src/mcpl/toolset-host.js.map +1 -1
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
- package/dist/src/mcpl/toolsets-module.js +2 -1
- package/dist/src/mcpl/toolsets-module.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +33 -6
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/module-registry.d.ts +24 -1
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +68 -18
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +45 -8
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +238 -87
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/health/index.js +2 -2
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +59 -0
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +432 -67
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +6 -5
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +18 -25
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +1 -1
- package/dist/src/modules/workspace/index.d.ts +28 -7
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +80 -25
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +2 -1
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +3 -2
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/notice-tags.d.ts +20 -9
- package/dist/src/notice-tags.d.ts.map +1 -1
- package/dist/src/notice-tags.js +20 -9
- package/dist/src/notice-tags.js.map +1 -1
- package/dist/src/operator-log.d.ts +36 -3
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js +2 -2
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/presentation.d.ts +747 -0
- package/dist/src/presentation.d.ts.map +1 -0
- package/dist/src/presentation.js +1437 -0
- package/dist/src/presentation.js.map +1 -0
- package/dist/src/prose-drafts.d.ts +15 -11
- package/dist/src/prose-drafts.d.ts.map +1 -1
- package/dist/src/prose-drafts.js +16 -12
- package/dist/src/prose-drafts.js.map +1 -1
- package/dist/src/read-marks.d.ts +192 -0
- package/dist/src/read-marks.d.ts.map +1 -0
- package/dist/src/read-marks.js +242 -0
- package/dist/src/read-marks.js.map +1 -0
- package/dist/src/reasoning-loss.d.ts +5 -0
- package/dist/src/reasoning-loss.d.ts.map +1 -0
- package/dist/src/reasoning-loss.js +8 -0
- package/dist/src/reasoning-loss.js.map +1 -0
- package/dist/src/recovery/offline-branch.d.ts +91 -6
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +277 -32
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js +24 -4
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/send-tools.d.ts +5 -9
- package/dist/src/send-tools.d.ts.map +1 -1
- package/dist/src/send-tools.js +40 -7
- package/dist/src/send-tools.js.map +1 -1
- package/dist/src/sent-rows.js +1 -1
- package/dist/src/stored-injections.d.ts +2 -2
- package/dist/src/stored-injections.js +2 -2
- package/dist/src/stored-removal.d.ts +17 -4
- package/dist/src/stored-removal.d.ts.map +1 -1
- package/dist/src/stored-removal.js +29 -5
- package/dist/src/stored-removal.js.map +1 -1
- package/dist/src/supplied-text.d.ts +1 -1
- package/dist/src/supplied-text.js +3 -3
- package/dist/src/supplied-text.js.map +1 -1
- package/dist/src/thinking-drops.d.ts +2 -0
- package/dist/src/thinking-drops.d.ts.map +1 -1
- package/dist/src/thinking-drops.js.map +1 -1
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +38 -9
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +12 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +42 -8
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +1170 -81
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +3732 -369
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +114 -17
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/tune-out/tools.js +89 -28
- package/dist/src/tune-out/tools.js.map +1 -1
- package/dist/src/tune-out/window-anchor.d.ts +143 -0
- package/dist/src/tune-out/window-anchor.d.ts.map +1 -0
- package/dist/src/tune-out/window-anchor.js +202 -0
- package/dist/src/tune-out/window-anchor.js.map +1 -0
- package/dist/src/types/agent.d.ts +121 -25
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +2 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +72 -17
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/inference-log.d.ts +1 -0
- package/dist/src/types/inference-log.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +180 -69
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +573 -39
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/admission/admit.ts +32 -3
- package/src/agent.ts +392 -132
- package/src/api/mcp-server-core.ts +54 -17
- package/src/api/server.ts +4 -23
- package/src/append-all.ts +6 -0
- package/src/code-execution/isolate/scripts.ts +28 -3
- package/src/config-checks.ts +14 -0
- package/src/context-manager-errors.ts +37 -0
- package/src/context-options.ts +106 -0
- package/src/cut-off-round.ts +4 -4
- package/src/deferred-import.ts +239 -0
- package/src/dendrite/audience.ts +315 -0
- package/src/dendrite/index.ts +14 -2
- package/src/dendrite/presets.ts +18 -6
- package/src/dendrite/registry.ts +213 -14
- package/src/dendrite/types.ts +92 -8
- package/src/failure-text.ts +88 -0
- package/src/foreign-rounds.ts +199 -0
- package/src/framework.ts +8796 -3813
- package/src/gate/event-gate.ts +518 -91
- package/src/gate/index.ts +3 -0
- package/src/gate/reply-judge.ts +12 -3
- package/src/gate/rule-scope.ts +45 -0
- package/src/gate/suppress-script-worker.ts +89 -0
- package/src/gate/suppress-scripts.ts +414 -0
- package/src/gate/suppression-review.ts +517 -0
- package/src/gate/suppression-stats.ts +314 -0
- package/src/gate/types.ts +148 -7
- package/src/gate/wake-onboarding.ts +309 -0
- package/src/heartbeat/heartbeat.ts +1 -1
- package/src/held-writes.ts +49 -60
- package/src/index.ts +10 -2
- package/src/inference-bounds.ts +11 -6
- package/src/jsonrpc-envelope.ts +81 -0
- package/src/mcpl/channel-registry.ts +513 -116
- package/src/mcpl/checkpoint-manager.ts +3 -2
- package/src/mcpl/feature-set-manager.ts +2 -1
- package/src/mcpl/inbound-source.ts +2 -1
- package/src/mcpl/inference-router.ts +7 -4
- package/src/mcpl/modern-connection.ts +629 -91
- package/src/mcpl/protocol-family.ts +15 -9
- package/src/mcpl/push-coalescer.ts +193 -34
- package/src/mcpl/push-handler.ts +10 -5
- package/src/mcpl/server-connection.ts +169 -75
- package/src/mcpl/tool-classes.ts +3 -0
- package/src/mcpl/tool-presence.ts +10 -5
- package/src/mcpl/toolset-host.ts +7 -6
- package/src/mcpl/toolsets-module.ts +2 -1
- package/src/mcpl/types.ts +33 -6
- package/src/module-registry.ts +73 -17
- package/src/modules/discord/index.ts +230 -82
- package/src/modules/health/index.ts +2 -2
- package/src/modules/history/index.ts +439 -70
- package/src/modules/history/semantic.ts +18 -24
- package/src/modules/workspace/disk-agreement.ts +1 -1
- package/src/modules/workspace/index.ts +89 -26
- package/src/modules/workspace/observe.ts +2 -1
- package/src/modules/workspace/reconcile.ts +3 -2
- package/src/notice-tags.ts +21 -9
- package/src/operator-log.ts +36 -3
- package/src/presentation.ts +1678 -0
- package/src/prose-drafts.ts +16 -12
- package/src/read-marks.ts +328 -0
- package/src/reasoning-loss.ts +7 -0
- package/src/recovery/offline-branch.ts +350 -35
- package/src/recovery/recover-cli.ts +23 -4
- package/src/send-tools.ts +40 -7
- package/src/sent-rows.ts +1 -1
- package/src/stored-injections.ts +2 -2
- package/src/stored-removal.ts +31 -7
- package/src/supplied-text.ts +3 -3
- package/src/thinking-drops.ts +2 -0
- package/src/tool-presentation.ts +34 -9
- package/src/tool-result-guard.ts +41 -7
- package/src/tune-out/coordinator.ts +4121 -472
- package/src/tune-out/tools.ts +162 -44
- package/src/tune-out/window-anchor.ts +277 -0
- package/src/types/agent.ts +122 -25
- package/src/types/events.ts +2 -0
- package/src/types/framework.ts +73 -17
- package/src/types/inference-log.ts +1 -0
- package/src/types/module.ts +181 -68
- package/src/types/trace.ts +607 -43
|
@@ -61,8 +61,8 @@ export declare class DiscordModule implements Module {
|
|
|
61
61
|
private syncAllChannelHistory;
|
|
62
62
|
/**
|
|
63
63
|
* Sync history for a specific channel - compare with Context Manager and update.
|
|
64
|
-
* Uses queryMessages() to enumerate the channel's rows,
|
|
65
|
-
*
|
|
64
|
+
* Uses queryMessages() to enumerate the channel's stored rows, for proper
|
|
65
|
+
* edit/delete detection.
|
|
66
66
|
*
|
|
67
67
|
* The live path can store, edit or remove a row whenever the sync awaits.
|
|
68
68
|
* So the sync fetches history and runs the live conversion it needs first,
|
|
@@ -81,18 +81,22 @@ export declare class DiscordModule implements Module {
|
|
|
81
81
|
* edit replaces a row's own text and keeps what the host added beside it.
|
|
82
82
|
* Each id's rows are in store order. A message stored twice holds two,
|
|
83
83
|
* of which a sync acts on the first, as the live path does (storedRow),
|
|
84
|
-
* and a delete takes both. A
|
|
85
|
-
* (storedRows). */
|
|
84
|
+
* and a delete takes both. A row the agent hasn't been shown yet (`held`)
|
|
85
|
+
* is a stored row as any other (storedRows). */
|
|
86
86
|
private storedByDiscordId;
|
|
87
87
|
/** The stored rows of a Discord message, by its id in the row's metadata,
|
|
88
|
-
* in store order.
|
|
89
|
-
*
|
|
88
|
+
* in store order. Every write is stored (#291), but for one a surgery's
|
|
89
|
+
* hold or a context manager refusing its work keeps in memory, which a
|
|
90
|
+
* restart loses: a row the agent's window doesn't hold yet reads `held`
|
|
91
|
+
* (one a tune-out holds reads `heldFromResidents`, whatever its window),
|
|
92
|
+
* in its place, and an edit or a removal
|
|
93
|
+
* reaches it as any other, and every window that holds it. The
|
|
90
94
|
* module context's findMessageByExternalId holds only rows the module
|
|
91
95
|
* stored through its context, not those a process response added, so it
|
|
92
96
|
* misses what the live path stored. */
|
|
93
97
|
private storedRows;
|
|
94
|
-
/** The row an edit or a create acts on: a message's first row
|
|
95
|
-
*
|
|
98
|
+
/** The row an edit or a create acts on: a message's first row in store
|
|
99
|
+
* order (storedRows). */
|
|
96
100
|
private storedRow;
|
|
97
101
|
/** Marks a Discord message as the live path's for every history sync running now. */
|
|
98
102
|
private noteLive;
|
|
@@ -108,6 +112,39 @@ export declare class DiscordModule implements Module {
|
|
|
108
112
|
*/
|
|
109
113
|
private shouldTriggerInference;
|
|
110
114
|
private handleDiscordMessageEdit;
|
|
115
|
+
private answerEdit;
|
|
116
|
+
private answerDelete;
|
|
117
|
+
/**
|
|
118
|
+
* A write the release of a surgery's hold couldn't store (`message:lost`):
|
|
119
|
+
* an answered create of the message (`writing`) with no row then ends,
|
|
120
|
+
* with the edits or delete kept for it (LiveCreate.unapplied), since no
|
|
121
|
+
* row comes for them to reach. Its delete, a history sync and a live
|
|
122
|
+
* create of the message are no longer passed over. A definite loss
|
|
123
|
+
* stored none of it, so it ends with no read. One whose outcome is
|
|
124
|
+
* unknown (`mayBeStored`) is looked for: where its row landed, no
|
|
125
|
+
* `message:added` came for it, so what was kept for it is applied now,
|
|
126
|
+
* and the entry waits, as any answered create, for the next Discord event
|
|
127
|
+
* to find the row. Where that lookup throws, the entry is flagged
|
|
128
|
+
* (`lostUnread`), and the next event's sweep that reads the store ends it
|
|
129
|
+
* where it finds no row.
|
|
130
|
+
*/
|
|
131
|
+
private endLostCreate;
|
|
132
|
+
/**
|
|
133
|
+
* The row of an answered create, looked for at an event's sweep, or
|
|
134
|
+
* undefined where the lookup throws, which is logged: that entry waits
|
|
135
|
+
* for the next event, and the others are swept all the same.
|
|
136
|
+
*/
|
|
137
|
+
private sweptRow;
|
|
138
|
+
/**
|
|
139
|
+
* Ends each answered create (`writing`) whose row a query shows now
|
|
140
|
+
* (sweptRow), but one still holding what was kept for it, which
|
|
141
|
+
* applyUnapplied couldn't apply (its lookup threw): it waits for the
|
|
142
|
+
* next event, so what was kept isn't dropped with it. A lost create
|
|
143
|
+
* whose release's lookup threw (`lostUnread`) ends where the lookup now
|
|
144
|
+
* reads no row: no row comes for it.
|
|
145
|
+
*/
|
|
146
|
+
private endShownCreates;
|
|
147
|
+
private applyUnapplied;
|
|
111
148
|
private handleDiscordMessageDelete;
|
|
112
149
|
/** Record a message the agent posted in a turn, for that turn's thoughts (lastPosts). */
|
|
113
150
|
private notePost;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/discord/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,UAAU,EACV,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EAInB,sBAAsB,EAiBvB,MAAM,YAAY,CAAC;AAQpB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE5F,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/discord/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -317,18 +317,24 @@ export class DiscordModule {
|
|
|
317
317
|
liveDuringSync = new Set();
|
|
318
318
|
// The Discord messages whose live create is on its way to the store: from
|
|
319
319
|
// the moment the live path takes one up, through its conversion and the
|
|
320
|
-
// event queue, until a query shows the row onProcess answered with
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
320
|
+
// event queue, until a query shows the row onProcess answered with. The
|
|
321
|
+
// framework stores a module's write at once, whatever the agent's turn or
|
|
322
|
+
// the host's mode (#291); only a live operator surgery's hold, or a context
|
|
323
|
+
// manager refusing its work, keeps it in memory, which a restart loses,
|
|
324
|
+
// until the release or the branch move that re-initializes the manager
|
|
325
|
+
// stores it. So the next Discord event once it is stored
|
|
326
|
+
// finds its row, marked held while the agent's window doesn't hold it
|
|
327
|
+
// (asModuleRow), and ends its entry. A history sync stores none of these messages, so no message is
|
|
325
328
|
// stored twice. A delete before the create is handled drops it: nothing is
|
|
326
329
|
// stored and nobody is woken. Any message's entry ends when its delete is
|
|
327
330
|
// handled, since a sync running then skips the message (noteLive) and a
|
|
328
|
-
// later one doesn't fetch it
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
331
|
+
// later one doesn't fetch it, but for an answered create with no row yet
|
|
332
|
+
// (`writing`), whose entry keeps its delete for the release that stores
|
|
333
|
+
// it (LiveCreate.unapplied). An edit while it converts is folded into it.
|
|
334
|
+
// A create whose answer the framework fails to write shows no row,
|
|
335
|
+
// and keeps its entry, and the sync off its message, until the module
|
|
336
|
+
// stops, but for one a surgery's hold kept, whose release, losing it,
|
|
337
|
+
// ends its entry (`message:lost`, endLostCreate).
|
|
332
338
|
creating = new Map();
|
|
333
339
|
// Typing keepalive: agentName -> { interval, deadline }. Started on
|
|
334
340
|
// inference:started, stopped on the turn's terminal trace event. Discord's
|
|
@@ -357,19 +363,31 @@ export class DiscordModule {
|
|
|
357
363
|
// inference and its turn ending, so it stays alive for the whole turn
|
|
358
364
|
// (including tool-call cycles) and stops cleanly whether the agent
|
|
359
365
|
// responds, errors, or decides to stay silent.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
366
|
+
this.unsubscribeTrace = ctx.onTrace((event) => {
|
|
367
|
+
// The edits and deletes kept for a held create are applied, or its
|
|
368
|
+
// record ended, on the trace of the surgery's release that stores or
|
|
369
|
+
// loses it (applyUnapplied, endLostCreate): the exception the README
|
|
370
|
+
// names to traces being observability-only.
|
|
371
|
+
if (event.type === 'message:added' && event.source === 'surgery-release') {
|
|
372
|
+
this.applyUnapplied();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (event.type === 'message:lost' && event.external?.source === 'discord') {
|
|
376
|
+
this.endLostCreate(event.external.id, event.mayBeStored === true);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
if (!this.config.autoTyping)
|
|
380
|
+
return;
|
|
381
|
+
const agentName = event.agentName;
|
|
382
|
+
if (!agentName)
|
|
383
|
+
return;
|
|
384
|
+
if (event.type === 'inference:started' && !event.silent) {
|
|
385
|
+
this.startTypingLoop(agentName);
|
|
386
|
+
}
|
|
387
|
+
else if (TURN_TERMINAL_TRACES.has(event.type)) {
|
|
388
|
+
this.stopTypingLoop(agentName);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
373
391
|
// Set up Discord event handlers
|
|
374
392
|
this.client.onMessage((message) => this.handleDiscordMessage(message));
|
|
375
393
|
this.client.onMessageEdit((id, content, attachments) => this.handleDiscordMessageEdit(id, content, attachments));
|
|
@@ -668,12 +686,13 @@ export class DiscordModule {
|
|
|
668
686
|
// A stopped module answers nothing (stop()).
|
|
669
687
|
if (!this.ctx)
|
|
670
688
|
return {};
|
|
671
|
-
// Each Discord event ends the entries whose row a query shows now,
|
|
672
|
-
//
|
|
689
|
+
// Each Discord event ends the entries whose row a query shows now,
|
|
690
|
+
// having applied what was kept for them first (applyUnapplied): an
|
|
691
|
+
// entry kept where its lost create's read threw (endLostCreate) still
|
|
692
|
+
// holds the edits or the delete made while its create was held.
|
|
673
693
|
if (event.type.startsWith('discord:')) {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
this.creating.delete(id);
|
|
694
|
+
this.applyUnapplied();
|
|
695
|
+
this.endShownCreates();
|
|
677
696
|
}
|
|
678
697
|
// Handle new Discord message
|
|
679
698
|
if (event.type === 'discord:message') {
|
|
@@ -725,7 +744,7 @@ export class DiscordModule {
|
|
|
725
744
|
// when an event carries no blocks; text first, as TEXT_FIRST marks.
|
|
726
745
|
const contentBlocks = msg.contentBlocks ?? textFirst(storedOwnText(msg.content));
|
|
727
746
|
this.noteLive(msg.discordMessageId);
|
|
728
|
-
// A message a history sync wrote first
|
|
747
|
+
// A message a history sync wrote first keeps that row:
|
|
729
748
|
// the create adds none, and still sets the reply context and asks for
|
|
730
749
|
// inference, since the message arrived live. Either way the entry waits
|
|
731
750
|
// until a Discord event finds the message's row.
|
|
@@ -754,54 +773,11 @@ export class DiscordModule {
|
|
|
754
773
|
};
|
|
755
774
|
}
|
|
756
775
|
// Handle Discord message edit
|
|
757
|
-
if (event.type === 'discord:edit')
|
|
758
|
-
|
|
759
|
-
// The message's row, not only its id: an edit changes the message's own
|
|
760
|
-
// text and keeps what the host added beside it, but for the blocks of
|
|
761
|
-
// attachments the edit took away, when the client passed the edit's
|
|
762
|
-
// attachments and the row is text-first.
|
|
763
|
-
// An edit that comes while the live path converts the message's create
|
|
764
|
-
// is folded into that create (handleDiscordMessageEdit). Any other edit
|
|
765
|
-
// to a message with no row, stored or held, is dropped: a history sync
|
|
766
|
-
// running now stores the text it fetched, and the next sync's text rule
|
|
767
|
-
// changes it. A row stored in shards can't be edited one shard at a
|
|
768
|
-
// time, so it keeps its text, and the host's log says so. Only an edit
|
|
769
|
-
// that writes marks the message live, so an update that changes nothing
|
|
770
|
-
// leaves a running sync free to rewrite the row.
|
|
771
|
-
const stored = this.storedRow(edit.discordMessageId);
|
|
772
|
-
if (!stored)
|
|
773
|
-
return {};
|
|
774
|
-
if (stored.bodyGroupId) {
|
|
775
|
-
console.warn(`Discord: An update to message ${edit.discordMessageId} wasn't applied: it's stored in shards, which can't be edited, so if its text changed, the agent still has the earlier text`);
|
|
776
|
-
return {};
|
|
777
|
-
}
|
|
778
|
-
const texted = contentForText(stored, edit.newContent);
|
|
779
|
-
const content = edit.attachments && stored.metadata?.[TEXT_FIRST] === true
|
|
780
|
-
? withoutGoneAttachments(texted ?? stored.content, edit.attachments)
|
|
781
|
-
: texted;
|
|
782
|
-
if (!content || content === stored.content)
|
|
783
|
-
return {};
|
|
784
|
-
this.noteLive(edit.discordMessageId);
|
|
785
|
-
return { editMessages: [{ messageId: stored.id, content }] };
|
|
786
|
-
}
|
|
776
|
+
if (event.type === 'discord:edit')
|
|
777
|
+
return this.answerEdit(event);
|
|
787
778
|
// Handle Discord message delete
|
|
788
|
-
if (event.type === 'discord:delete')
|
|
789
|
-
|
|
790
|
-
// Every row of the message goes, so one stored twice doesn't outlive
|
|
791
|
-
// its delete as a copy. A row stored in shards is removed whole: the
|
|
792
|
-
// framework takes out the body a shard belongs to. The message is the
|
|
793
|
-
// live path's even when no row is found, so a running sync doesn't
|
|
794
|
-
// store what its fetch may still hold, and that ends its entry.
|
|
795
|
-
this.noteLive(del.discordMessageId);
|
|
796
|
-
this.creating.delete(del.discordMessageId);
|
|
797
|
-
const rows = this.storedRows(del.discordMessageId);
|
|
798
|
-
if (rows.length === 0) {
|
|
799
|
-
return {};
|
|
800
|
-
}
|
|
801
|
-
return {
|
|
802
|
-
removeMessages: oncePerBody(rows),
|
|
803
|
-
};
|
|
804
|
-
}
|
|
779
|
+
if (event.type === 'discord:delete')
|
|
780
|
+
return this.answerDelete(event);
|
|
805
781
|
return {};
|
|
806
782
|
}
|
|
807
783
|
/**
|
|
@@ -934,8 +910,8 @@ export class DiscordModule {
|
|
|
934
910
|
}
|
|
935
911
|
/**
|
|
936
912
|
* Sync history for a specific channel - compare with Context Manager and update.
|
|
937
|
-
* Uses queryMessages() to enumerate the channel's rows,
|
|
938
|
-
*
|
|
913
|
+
* Uses queryMessages() to enumerate the channel's stored rows, for proper
|
|
914
|
+
* edit/delete detection.
|
|
939
915
|
*
|
|
940
916
|
* The live path can store, edit or remove a row whenever the sync awaits.
|
|
941
917
|
* So the sync fetches history and runs the live conversion it needs first,
|
|
@@ -1038,7 +1014,7 @@ export class DiscordModule {
|
|
|
1038
1014
|
// boundary whose tied millisecond must be preserved.
|
|
1039
1015
|
const fetchedCompleteHistory = discordMessages.length < scrollback;
|
|
1040
1016
|
const oldestFetchedTimestamp = discordMessages.length > 0
|
|
1041
|
-
?
|
|
1017
|
+
? discordMessages.reduce((min, msg) => Math.min(min, msg.timestamp.getTime()), Infinity)
|
|
1042
1018
|
: undefined;
|
|
1043
1019
|
for (const [externalId, rows] of storedMessageMap) {
|
|
1044
1020
|
const stored = rows[0];
|
|
@@ -1078,8 +1054,8 @@ export class DiscordModule {
|
|
|
1078
1054
|
* edit replaces a row's own text and keeps what the host added beside it.
|
|
1079
1055
|
* Each id's rows are in store order. A message stored twice holds two,
|
|
1080
1056
|
* of which a sync acts on the first, as the live path does (storedRow),
|
|
1081
|
-
* and a delete takes both. A
|
|
1082
|
-
* (storedRows). */
|
|
1057
|
+
* and a delete takes both. A row the agent hasn't been shown yet (`held`)
|
|
1058
|
+
* is a stored row as any other (storedRows). */
|
|
1083
1059
|
storedByDiscordId(ctx, channelId) {
|
|
1084
1060
|
const rows = new Map();
|
|
1085
1061
|
for (const msg of ctx.queryMessages({ source: 'discord', metadata: { channelId } }).messages) {
|
|
@@ -1095,16 +1071,20 @@ export class DiscordModule {
|
|
|
1095
1071
|
return rows;
|
|
1096
1072
|
}
|
|
1097
1073
|
/** The stored rows of a Discord message, by its id in the row's metadata,
|
|
1098
|
-
* in store order.
|
|
1099
|
-
*
|
|
1074
|
+
* in store order. Every write is stored (#291), but for one a surgery's
|
|
1075
|
+
* hold or a context manager refusing its work keeps in memory, which a
|
|
1076
|
+
* restart loses: a row the agent's window doesn't hold yet reads `held`
|
|
1077
|
+
* (one a tune-out holds reads `heldFromResidents`, whatever its window),
|
|
1078
|
+
* in its place, and an edit or a removal
|
|
1079
|
+
* reaches it as any other, and every window that holds it. The
|
|
1100
1080
|
* module context's findMessageByExternalId holds only rows the module
|
|
1101
1081
|
* stored through its context, not those a process response added, so it
|
|
1102
1082
|
* misses what the live path stored. */
|
|
1103
1083
|
storedRows(discordMessageId) {
|
|
1104
1084
|
return this.ctx?.queryMessages({ source: 'discord', externalIds: [discordMessageId] }).messages ?? [];
|
|
1105
1085
|
}
|
|
1106
|
-
/** The row an edit or a create acts on: a message's first row
|
|
1107
|
-
*
|
|
1086
|
+
/** The row an edit or a create acts on: a message's first row in store
|
|
1087
|
+
* order (storedRows). */
|
|
1108
1088
|
storedRow(discordMessageId) {
|
|
1109
1089
|
return this.storedRows(discordMessageId)[0];
|
|
1110
1090
|
}
|
|
@@ -1308,14 +1288,185 @@ export class DiscordModule {
|
|
|
1308
1288
|
...(attachments ? { attachments } : {}),
|
|
1309
1289
|
});
|
|
1310
1290
|
}
|
|
1291
|
+
answerEdit(edit) {
|
|
1292
|
+
// The message's row, not only its id: an edit changes the message's own
|
|
1293
|
+
// text and keeps what the host added beside it, but for the blocks of
|
|
1294
|
+
// attachments the edit took away, when the client passed the edit's
|
|
1295
|
+
// attachments and the row is text-first.
|
|
1296
|
+
// An edit that comes while the live path converts the message's create
|
|
1297
|
+
// is folded into that create (handleDiscordMessageEdit). One that comes
|
|
1298
|
+
// once onProcess answered the create and finds no row is kept on its
|
|
1299
|
+
// entry (LiveCreate.unapplied), unless a delete is kept there already,
|
|
1300
|
+
// and so is one that comes while edits kept there wait for a sweep that
|
|
1301
|
+
// finds the row (sweptRow threw, or the row came after the sweep): it
|
|
1302
|
+
// goes behind them, and applyUnapplied applies them in order, so an
|
|
1303
|
+
// older kept edit never lands over it. Any other edit
|
|
1304
|
+
// to a message with no row is dropped: a history sync
|
|
1305
|
+
// running now stores the text it fetched, and the next sync's text rule
|
|
1306
|
+
// changes it. A row stored in shards can't be edited one shard at a
|
|
1307
|
+
// time, so it keeps its text, and the host's log says so. Only an edit
|
|
1308
|
+
// that writes marks the message live, so an update that changes nothing
|
|
1309
|
+
// leaves a running sync free to rewrite the row.
|
|
1310
|
+
const kept = this.creating.get(edit.discordMessageId);
|
|
1311
|
+
const keep = () => {
|
|
1312
|
+
if (kept?.phase === 'writing' && kept.unapplied !== 'delete') {
|
|
1313
|
+
kept.unapplied = [...(kept.unapplied ?? []), { text: edit.newContent, ...(edit.attachments ? { attachments: edit.attachments } : {}) }];
|
|
1314
|
+
}
|
|
1315
|
+
return {};
|
|
1316
|
+
};
|
|
1317
|
+
if (kept?.phase === 'writing' && Array.isArray(kept.unapplied))
|
|
1318
|
+
return keep();
|
|
1319
|
+
const stored = this.storedRow(edit.discordMessageId);
|
|
1320
|
+
if (!stored)
|
|
1321
|
+
return keep();
|
|
1322
|
+
if (stored.bodyGroupId) {
|
|
1323
|
+
console.warn(`Discord: An update to message ${edit.discordMessageId} wasn't applied: it's stored in shards, which can't be edited, so if its text changed, the agent still has the earlier text`);
|
|
1324
|
+
return {};
|
|
1325
|
+
}
|
|
1326
|
+
const texted = contentForText(stored, edit.newContent);
|
|
1327
|
+
const content = edit.attachments && stored.metadata?.[TEXT_FIRST] === true
|
|
1328
|
+
? withoutGoneAttachments(texted ?? stored.content, edit.attachments)
|
|
1329
|
+
: texted;
|
|
1330
|
+
if (!content || content === stored.content)
|
|
1331
|
+
return {};
|
|
1332
|
+
this.noteLive(edit.discordMessageId);
|
|
1333
|
+
return { editMessages: [{ messageId: stored.id, content }] };
|
|
1334
|
+
}
|
|
1335
|
+
answerDelete(del) {
|
|
1336
|
+
// Every row of the message goes, so one stored twice doesn't outlive
|
|
1337
|
+
// its delete as a copy. A row stored in shards is removed whole: the
|
|
1338
|
+
// framework takes out the body a shard belongs to. The message is the
|
|
1339
|
+
// live path's even when no row is found, so a running sync doesn't
|
|
1340
|
+
// store what its fetch may still hold, and that ends its entry, but for
|
|
1341
|
+
// an answered create with no row, whose entry keeps the delete its
|
|
1342
|
+
// handler recorded (LiveCreate.unapplied) for the release.
|
|
1343
|
+
this.noteLive(del.discordMessageId);
|
|
1344
|
+
const rows = this.storedRows(del.discordMessageId);
|
|
1345
|
+
if (rows.length === 0 && this.creating.get(del.discordMessageId)?.phase === 'writing')
|
|
1346
|
+
return {};
|
|
1347
|
+
this.creating.delete(del.discordMessageId);
|
|
1348
|
+
if (rows.length === 0) {
|
|
1349
|
+
return {};
|
|
1350
|
+
}
|
|
1351
|
+
return {
|
|
1352
|
+
removeMessages: oncePerBody(rows),
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* A write the release of a surgery's hold couldn't store (`message:lost`):
|
|
1357
|
+
* an answered create of the message (`writing`) with no row then ends,
|
|
1358
|
+
* with the edits or delete kept for it (LiveCreate.unapplied), since no
|
|
1359
|
+
* row comes for them to reach. Its delete, a history sync and a live
|
|
1360
|
+
* create of the message are no longer passed over. A definite loss
|
|
1361
|
+
* stored none of it, so it ends with no read. One whose outcome is
|
|
1362
|
+
* unknown (`mayBeStored`) is looked for: where its row landed, no
|
|
1363
|
+
* `message:added` came for it, so what was kept for it is applied now,
|
|
1364
|
+
* and the entry waits, as any answered create, for the next Discord event
|
|
1365
|
+
* to find the row. Where that lookup throws, the entry is flagged
|
|
1366
|
+
* (`lostUnread`), and the next event's sweep that reads the store ends it
|
|
1367
|
+
* where it finds no row.
|
|
1368
|
+
*/
|
|
1369
|
+
endLostCreate(discordMessageId, mayBeStored) {
|
|
1370
|
+
if (this.creating.get(discordMessageId)?.phase !== 'writing')
|
|
1371
|
+
return;
|
|
1372
|
+
if (mayBeStored) {
|
|
1373
|
+
let landed;
|
|
1374
|
+
try {
|
|
1375
|
+
landed = this.storedRow(discordMessageId) !== undefined;
|
|
1376
|
+
}
|
|
1377
|
+
catch (error) {
|
|
1378
|
+
console.error(`Discord: whether message ${discordMessageId}'s lost create left a row couldn't be read, so its record waits for the next event to find its row:`, error);
|
|
1379
|
+
const live = this.creating.get(discordMessageId);
|
|
1380
|
+
if (live)
|
|
1381
|
+
live.lostUnread = true;
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
if (landed) {
|
|
1385
|
+
this.applyUnapplied();
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
this.creating.delete(discordMessageId);
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* The row of an answered create, looked for at an event's sweep, or
|
|
1393
|
+
* undefined where the lookup throws, which is logged: that entry waits
|
|
1394
|
+
* for the next event, and the others are swept all the same.
|
|
1395
|
+
*/
|
|
1396
|
+
sweptRow(discordMessageId) {
|
|
1397
|
+
try {
|
|
1398
|
+
return { row: this.storedRow(discordMessageId) };
|
|
1399
|
+
}
|
|
1400
|
+
catch (error) {
|
|
1401
|
+
console.error(`Discord: whether message ${discordMessageId}'s create left a row couldn't be read, so its record waits for the next event:`, error);
|
|
1402
|
+
return undefined;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Ends each answered create (`writing`) whose row a query shows now
|
|
1407
|
+
* (sweptRow), but one still holding what was kept for it, which
|
|
1408
|
+
* applyUnapplied couldn't apply (its lookup threw): it waits for the
|
|
1409
|
+
* next event, so what was kept isn't dropped with it. A lost create
|
|
1410
|
+
* whose release's lookup threw (`lostUnread`) ends where the lookup now
|
|
1411
|
+
* reads no row: no row comes for it.
|
|
1412
|
+
*/
|
|
1413
|
+
endShownCreates() {
|
|
1414
|
+
for (const [id, live] of this.creating) {
|
|
1415
|
+
if (live.phase !== 'writing')
|
|
1416
|
+
continue;
|
|
1417
|
+
const swept = this.sweptRow(id);
|
|
1418
|
+
if (swept === undefined)
|
|
1419
|
+
continue;
|
|
1420
|
+
if (swept.row ? live.unapplied === undefined : live.lostUnread)
|
|
1421
|
+
this.creating.delete(id);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
applyUnapplied() {
|
|
1425
|
+
const ctx = this.ctx;
|
|
1426
|
+
if (!ctx)
|
|
1427
|
+
return;
|
|
1428
|
+
for (const [discordMessageId, live] of this.creating) {
|
|
1429
|
+
const unapplied = live.unapplied;
|
|
1430
|
+
if (unapplied === undefined || !this.sweptRow(discordMessageId)?.row)
|
|
1431
|
+
continue;
|
|
1432
|
+
live.unapplied = undefined;
|
|
1433
|
+
const apply = (what, step) => {
|
|
1434
|
+
try {
|
|
1435
|
+
step();
|
|
1436
|
+
}
|
|
1437
|
+
catch (error) {
|
|
1438
|
+
console.error(`Discord: ${what} of message ${discordMessageId}, made while its create was kept in memory, threw as the release applied it, and may not have been applied:`, error);
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
if (unapplied === 'delete') {
|
|
1442
|
+
apply('the delete', () => {
|
|
1443
|
+
for (const id of this.answerDelete({ type: 'discord:delete', discordMessageId }).removeMessages ?? [])
|
|
1444
|
+
ctx.removeMessage(id);
|
|
1445
|
+
});
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
for (const { text, attachments } of unapplied) {
|
|
1449
|
+
apply('an edit', () => {
|
|
1450
|
+
const answer = this.answerEdit({ type: 'discord:edit', discordMessageId, newContent: text, ...(attachments ? { attachments } : {}) });
|
|
1451
|
+
for (const { messageId, content } of answer.editMessages ?? [])
|
|
1452
|
+
ctx.editMessage(messageId, content);
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1311
1457
|
handleDiscordMessageDelete(messageId) {
|
|
1312
1458
|
if (!this.ctx)
|
|
1313
1459
|
return;
|
|
1314
|
-
// A delete before the message's create is handled drops that create
|
|
1315
|
-
//
|
|
1460
|
+
// A delete before the message's create is handled drops that create,
|
|
1461
|
+
// and one after it was answered is kept on its entry for the release
|
|
1462
|
+
// that stores it (LiveCreate.unapplied). Its event still goes, for a row
|
|
1463
|
+
// a history sync stored first.
|
|
1316
1464
|
const live = this.creating.get(messageId);
|
|
1317
|
-
if (live)
|
|
1465
|
+
if (live) {
|
|
1318
1466
|
live.deleted = true;
|
|
1467
|
+
if (live.phase === 'writing')
|
|
1468
|
+
live.unapplied = 'delete';
|
|
1469
|
+
}
|
|
1319
1470
|
// Only queue the event - state writes happen in onProcess()
|
|
1320
1471
|
this.ctx.pushEvent({
|
|
1321
1472
|
type: 'discord:delete',
|