@soimy/dingtalk 3.6.11 → 3.7.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/dist/index.d.ts +1 -1
- package/dist/index.js +11684 -10583
- package/dist/src/{ack-reaction-service.d.ts → ack-reaction/ack-reaction-service.d.ts} +1 -1
- package/dist/src/ack-reaction/dynamic-ack-reaction-controller.d.ts +3 -3
- package/dist/src/card/ask-user-question-context.d.ts +1 -1
- package/dist/src/card/ask-user-question-store.d.ts +1 -1
- package/dist/src/card/ask-user-question.d.ts +1 -1
- package/dist/src/card/card-action-handler.d.ts +2 -2
- package/dist/src/{card-draft-controller.d.ts → card/card-draft-controller.d.ts} +5 -1
- package/dist/src/card/card-run-registry.d.ts +2 -2
- package/dist/src/{card-service.d.ts → card/card-service.d.ts} +1 -1
- package/dist/src/card/card-stop-handler.d.ts +1 -1
- package/dist/src/card/card-streaming-mode.d.ts +1 -1
- package/dist/src/card/card-task-progress.d.ts +60 -0
- package/dist/src/channel.d.ts +6 -6
- package/dist/src/command/card-stop-command.d.ts +1 -1
- package/dist/src/{feedback-learning-service.d.ts → command/feedback-learning-service.d.ts} +1 -1
- package/dist/src/command/inbound-command-dispatch-service.d.ts +2 -2
- package/dist/src/{learning-command-service.d.ts → command/learning-command-service.d.ts} +1 -1
- package/dist/src/gateway/channel-gateway.d.ts +1 -1
- package/dist/src/{connection-manager.d.ts → gateway/connection-manager.d.ts} +1 -1
- package/dist/src/{docs-service.d.ts → gateway/docs-service.d.ts} +1 -1
- package/dist/src/{inbound-handler.d.ts → gateway/inbound-handler.d.ts} +1 -1
- package/dist/src/gateway/inbound-session-queue-dispatcher.d.ts +1 -1
- package/dist/src/messaging/attachment-text-extractor.d.ts +1 -1
- package/dist/src/messaging/btw-deliver.d.ts +1 -1
- package/dist/src/messaging/channel-outbound.d.ts +1 -1
- package/dist/src/{media-utils.d.ts → messaging/media-utils.d.ts} +1 -1
- package/dist/src/{message-context-store.d.ts → messaging/message-context-store.d.ts} +7 -1
- package/dist/src/{message-utils.d.ts → messaging/message-utils.d.ts} +1 -1
- package/dist/src/messaging/quoted-context.d.ts +2 -2
- package/dist/src/messaging/quoted-file-service.d.ts +1 -1
- package/dist/src/messaging/quoted-ref.d.ts +2 -2
- package/dist/src/{reply-strategy-card.d.ts → messaging/reply-strategy-card.d.ts} +1 -1
- package/dist/src/{reply-strategy-types.d.ts → messaging/reply-strategy-types.d.ts} +10 -1
- package/dist/src/{reply-strategy-with-reaction.d.ts → messaging/reply-strategy-with-reaction.d.ts} +1 -1
- package/dist/src/{reply-strategy.d.ts → messaging/reply-strategy.d.ts} +1 -1
- package/dist/src/{send-service.d.ts → messaging/send-service.d.ts} +1 -1
- package/dist/src/platform/channel-status.d.ts +1 -1
- package/dist/src/platform/config.d.ts +110 -0
- package/dist/src/platform/runtime-events.d.ts +67 -0
- package/dist/src/{types.d.ts → platform/types.d.ts} +74 -1
- package/dist/src/{persistence-store.d.ts → shared/persistence-store.d.ts} +1 -1
- package/dist/src/{utils.d.ts → shared/utils.d.ts} +1 -1
- package/dist/src/targeting/agent-name-matcher.d.ts +1 -1
- package/dist/src/targeting/agent-routing.d.ts +3 -3
- package/dist/src/{session-routing.d.ts → targeting/session-routing.d.ts} +1 -1
- package/index.ts +193 -69
- package/openclaw.plugin.json +158 -2
- package/package.json +16 -16
- package/src/{ack-reaction-classifier.ts → ack-reaction/ack-reaction-classifier.ts} +85 -13
- package/src/{ack-reaction-service.ts → ack-reaction/ack-reaction-service.ts} +13 -7
- package/src/ack-reaction/dynamic-ack-reaction-controller.ts +46 -31
- package/src/ack-reaction/dynamic-ack-reaction-progress.ts +4 -1
- package/src/card/ask-user-question-context.ts +1 -1
- package/src/card/ask-user-question-store.ts +2 -2
- package/src/card/ask-user-question.ts +11 -7
- package/src/card/card-action-handler.ts +2 -2
- package/src/{card-callback-service.ts → card/card-callback-service.ts} +7 -9
- package/src/card/card-draft-controller.ts +770 -0
- package/src/card/card-markdown-image-reroute.ts +8 -2
- package/src/card/card-run-registry.ts +17 -7
- package/src/{card-service.ts → card/card-service.ts} +91 -61
- package/src/card/card-stop-handler.ts +12 -8
- package/src/card/card-streaming-mode.ts +1 -1
- package/src/card/card-task-progress.ts +330 -0
- package/src/card/draft-stream-loop.ts +119 -0
- package/src/card/reasoning-answer-split.ts +125 -121
- package/src/card/reasoning-block-assembler.ts +122 -123
- package/src/{run-usage-store.ts → card/run-usage-store.ts} +18 -6
- package/src/card/statusline-renderer.ts +14 -5
- package/src/card/task-model-metadata.ts +8 -3
- package/src/channel.ts +14 -16
- package/src/command/card-stop-command.ts +2 -2
- package/src/{feedback-learning-service.ts → command/feedback-learning-service.ts} +36 -16
- package/src/{feedback-learning-store.ts → command/feedback-learning-store.ts} +133 -81
- package/src/command/inbound-command-dispatch-service.ts +12 -6
- package/src/{learning-command-service.ts → command/learning-command-service.ts} +36 -29
- package/src/{session-command-service.ts → command/session-command-service.ts} +3 -1
- package/src/gateway/channel-gateway.ts +106 -28
- package/src/{connection-manager.ts → gateway/connection-manager.ts} +45 -30
- package/src/{docs-service.ts → gateway/docs-service.ts} +5 -5
- package/src/{inbound-handler.ts → gateway/inbound-handler.ts} +139 -84
- package/src/gateway/inbound-session-queue-dispatcher.ts +18 -14
- package/src/{session-lock.ts → gateway/session-lock.ts} +14 -14
- package/src/messaging/attachment-text-extractor.ts +21 -7
- package/src/messaging/btw-deliver.ts +2 -2
- package/src/messaging/channel-actions.ts +15 -7
- package/src/messaging/channel-outbound.ts +16 -11
- package/src/{media-utils.ts → messaging/media-utils.ts} +276 -72
- package/src/{message-context-store.ts → messaging/message-context-store.ts} +11 -2
- package/src/{message-utils.ts → messaging/message-utils.ts} +46 -11
- package/src/messaging/quoted-context.ts +2 -2
- package/src/messaging/quoted-file-service.ts +311 -294
- package/src/messaging/quoted-ref.ts +11 -7
- package/src/{reply-strategy-card.ts → messaging/reply-strategy-card.ts} +178 -101
- package/src/{reply-strategy-markdown.ts → messaging/reply-strategy-markdown.ts} +8 -2
- package/src/{reply-strategy-types.ts → messaging/reply-strategy-types.ts} +11 -1
- package/src/{reply-strategy-with-reaction.ts → messaging/reply-strategy-with-reaction.ts} +6 -1
- package/src/{reply-strategy.ts → messaging/reply-strategy.ts} +2 -2
- package/src/{send-service.ts → messaging/send-service.ts} +100 -65
- package/src/{auth.ts → platform/auth.ts} +2 -2
- package/src/platform/channel-status.ts +3 -3
- package/src/{config-schema.ts → platform/config-schema.ts} +81 -4
- package/src/{config.ts → platform/config.ts} +167 -19
- package/src/{device-registration.ts → platform/device-registration.ts} +5 -4
- package/src/{onboarding.ts → platform/onboarding.ts} +1 -4
- package/src/{plugin-sdk-channel-actions-augment.ts → platform/plugin-sdk-channel-actions-augment.ts} +6 -5
- package/src/platform/runtime-events.ts +202 -0
- package/src/{secret-input.ts → platform/secret-input.ts} +117 -11
- package/src/{types.ts → platform/types.ts} +76 -1
- package/src/{http-client.ts → shared/http-client.ts} +1 -3
- package/src/{persistence-store.ts → shared/persistence-store.ts} +6 -6
- package/src/{utils.ts → shared/utils.ts} +30 -13
- package/src/targeting/agent-name-matcher.ts +1 -1
- package/src/targeting/agent-routing.ts +7 -7
- package/src/targeting/group-members-store.ts +1 -1
- package/src/{session-peer-store.ts → targeting/session-peer-store.ts} +9 -4
- package/src/{session-routing.ts → targeting/session-routing.ts} +1 -1
- package/src/targeting/target-directory-adapter.ts +3 -3
- package/src/targeting/target-directory-store.ts +1 -1
- package/src/targeting/target-input.ts +1 -1
- package/dist/src/ack-reaction/dynamic-ack-reaction-events.d.ts +0 -35
- package/dist/src/config.d.ts +0 -59
- package/src/ack-reaction/dynamic-ack-reaction-events.ts +0 -123
- package/src/card-draft-controller.ts +0 -637
- package/src/draft-stream-loop.ts +0 -119
- /package/dist/src/{ack-reaction-classifier.d.ts → ack-reaction/ack-reaction-classifier.d.ts} +0 -0
- /package/dist/src/{card-callback-service.d.ts → card/card-callback-service.d.ts} +0 -0
- /package/dist/src/{draft-stream-loop.d.ts → card/draft-stream-loop.d.ts} +0 -0
- /package/dist/src/{run-usage-store.d.ts → card/run-usage-store.d.ts} +0 -0
- /package/dist/src/{feedback-learning-store.d.ts → command/feedback-learning-store.d.ts} +0 -0
- /package/dist/src/{session-command-service.d.ts → command/session-command-service.d.ts} +0 -0
- /package/dist/src/{session-lock.d.ts → gateway/session-lock.d.ts} +0 -0
- /package/dist/src/{proactive-risk-registry.d.ts → messaging/proactive-risk-registry.d.ts} +0 -0
- /package/dist/src/{reply-strategy-markdown.d.ts → messaging/reply-strategy-markdown.d.ts} +0 -0
- /package/dist/src/{access-control.d.ts → platform/access-control.d.ts} +0 -0
- /package/dist/src/{auth.d.ts → platform/auth.d.ts} +0 -0
- /package/dist/src/{config-schema.d.ts → platform/config-schema.d.ts} +0 -0
- /package/dist/src/{device-registration.d.ts → platform/device-registration.d.ts} +0 -0
- /package/dist/src/{logger-context.d.ts → platform/logger-context.d.ts} +0 -0
- /package/dist/src/{onboarding.d.ts → platform/onboarding.d.ts} +0 -0
- /package/dist/src/{plugin-sdk-channel-actions-augment.d.ts → platform/plugin-sdk-channel-actions-augment.d.ts} +0 -0
- /package/dist/src/{runtime.d.ts → platform/runtime.d.ts} +0 -0
- /package/dist/src/{secret-input.d.ts → platform/secret-input.d.ts} +0 -0
- /package/dist/src/{session-state.d.ts → platform/session-state.d.ts} +0 -0
- /package/dist/src/{signature.d.ts → platform/signature.d.ts} +0 -0
- /package/dist/src/{dedup.d.ts → shared/dedup.d.ts} +0 -0
- /package/dist/src/{http-client.d.ts → shared/http-client.d.ts} +0 -0
- /package/dist/src/{path-utils.d.ts → shared/path-utils.d.ts} +0 -0
- /package/dist/src/{peer-id-registry.d.ts → targeting/peer-id-registry.d.ts} +0 -0
- /package/dist/src/{session-peer-store.d.ts → targeting/session-peer-store.d.ts} +0 -0
- /package/src/{proactive-risk-registry.ts → messaging/proactive-risk-registry.ts} +0 -0
- /package/src/{access-control.ts → platform/access-control.ts} +0 -0
- /package/src/{logger-context.ts → platform/logger-context.ts} +0 -0
- /package/src/{runtime.ts → platform/runtime.ts} +0 -0
- /package/src/{session-state.ts → platform/session-state.ts} +0 -0
- /package/src/{signature.ts → platform/signature.ts} +0 -0
- /package/src/{dedup.ts → shared/dedup.ts} +0 -0
- /package/src/{path-utils.ts → shared/path-utils.ts} +0 -0
- /package/src/{peer-id-registry.ts → targeting/peer-id-registry.ts} +0 -0
package/openclaw.plugin.json
CHANGED
|
@@ -251,6 +251,15 @@
|
|
|
251
251
|
"default": 1000,
|
|
252
252
|
"description": "Throttle interval in milliseconds between AI card streaming updates."
|
|
253
253
|
},
|
|
254
|
+
"cardTaskProgress": {
|
|
255
|
+
"type": "boolean",
|
|
256
|
+
"description": "Live task-progress block on AI cards for long-running tasks. true forces it on, false forces it off; when unset it is on unless cardStreamingMode is explicitly set to off."
|
|
257
|
+
},
|
|
258
|
+
"cardTaskProgressRefresh": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"enum": ["heartbeat", "interval"],
|
|
261
|
+
"description": "How tool-driven progress changes reach the card. heartbeat (effective default) coalesces them into the 30-second refresh; interval pushes on every correlated tool event, throttled by cardStreamInterval."
|
|
262
|
+
},
|
|
254
263
|
"aicardDegradeMs": {
|
|
255
264
|
"type": "integer",
|
|
256
265
|
"minimum": 60000,
|
|
@@ -283,7 +292,14 @@
|
|
|
283
292
|
"type": "object",
|
|
284
293
|
"description": "Status line visibility toggles for the AI card footer.",
|
|
285
294
|
"additionalProperties": false,
|
|
286
|
-
"default": {
|
|
295
|
+
"default": {
|
|
296
|
+
"model": true,
|
|
297
|
+
"effort": true,
|
|
298
|
+
"agent": true,
|
|
299
|
+
"taskTime": false,
|
|
300
|
+
"tokens": false,
|
|
301
|
+
"dapiUsage": false
|
|
302
|
+
},
|
|
287
303
|
"properties": {
|
|
288
304
|
"model": {
|
|
289
305
|
"type": "boolean",
|
|
@@ -325,6 +341,54 @@
|
|
|
325
341
|
"type": "boolean",
|
|
326
342
|
"description": "Legacy compatibility field from older host or runtime integrations. It is not used by the current runtime and new configs should omit it."
|
|
327
343
|
},
|
|
344
|
+
"gatewayCapabilities": {
|
|
345
|
+
"type": "object",
|
|
346
|
+
"additionalProperties": false,
|
|
347
|
+
"description": "Capability gates and allowlists for docs Gateway RPCs (dingtalk.docs.* / dingtalk-connector.docs.*) and proactive-send Gateway RPCs (dingtalk-connector.sendToUser/sendToGroup/send). All capabilities default to enabled; these RPCs rely on the host Gateway trust model and do not authenticate the caller.",
|
|
348
|
+
"properties": {
|
|
349
|
+
"tools": {
|
|
350
|
+
"type": "object",
|
|
351
|
+
"additionalProperties": false,
|
|
352
|
+
"description": "Capability switches. Omitted switches default to enabled.",
|
|
353
|
+
"properties": {
|
|
354
|
+
"docs": {
|
|
355
|
+
"type": "boolean",
|
|
356
|
+
"description": "Enable dingtalk.docs.* and dingtalk-connector.docs.* Gateway RPCs. Defaults to true when omitted."
|
|
357
|
+
},
|
|
358
|
+
"proactiveSend": {
|
|
359
|
+
"type": "boolean",
|
|
360
|
+
"description": "Enable dingtalk-connector.sendToUser/sendToGroup/send proactive-send RPCs. Defaults to true when omitted."
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
"docs": {
|
|
365
|
+
"type": "object",
|
|
366
|
+
"additionalProperties": false,
|
|
367
|
+
"description": "Docs RPC allowlist. When allowedSpaceIds is configured, requests without a spaceId (for example dingtalk.docs.append) are denied as well.",
|
|
368
|
+
"properties": {
|
|
369
|
+
"allowedSpaceIds": {
|
|
370
|
+
"type": "array",
|
|
371
|
+
"minItems": 1,
|
|
372
|
+
"items": { "type": "string", "minLength": 1 },
|
|
373
|
+
"description": "When set, docs RPCs only accept these spaceId values."
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
"send": {
|
|
378
|
+
"type": "object",
|
|
379
|
+
"additionalProperties": false,
|
|
380
|
+
"description": "Proactive-send target allowlist.",
|
|
381
|
+
"properties": {
|
|
382
|
+
"allowedTargets": {
|
|
383
|
+
"type": "array",
|
|
384
|
+
"minItems": 1,
|
|
385
|
+
"items": { "type": "string", "pattern": "^(user|group):\\S+$" },
|
|
386
|
+
"description": "When set, proactive-send RPCs only accept these user:<id> or group:<conversationId> targets."
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
},
|
|
328
392
|
"accounts": {
|
|
329
393
|
"type": "object",
|
|
330
394
|
"description": "Named multi-account DingTalk configurations. Each account can override most top-level settings and inherits unspecified values from the top level.",
|
|
@@ -557,6 +621,15 @@
|
|
|
557
621
|
"default": 1000,
|
|
558
622
|
"description": "Throttle interval in milliseconds between AI card streaming updates."
|
|
559
623
|
},
|
|
624
|
+
"cardTaskProgress": {
|
|
625
|
+
"type": "boolean",
|
|
626
|
+
"description": "Live task-progress block on AI cards for long-running tasks. true forces it on, false forces it off; when unset it is on unless cardStreamingMode is explicitly set to off."
|
|
627
|
+
},
|
|
628
|
+
"cardTaskProgressRefresh": {
|
|
629
|
+
"type": "string",
|
|
630
|
+
"enum": ["heartbeat", "interval"],
|
|
631
|
+
"description": "How tool-driven progress changes reach the card. heartbeat (effective default) coalesces them into the 30-second refresh; interval pushes on every correlated tool event, throttled by cardStreamInterval."
|
|
632
|
+
},
|
|
560
633
|
"aicardDegradeMs": {
|
|
561
634
|
"type": "integer",
|
|
562
635
|
"minimum": 60000,
|
|
@@ -589,7 +662,14 @@
|
|
|
589
662
|
"type": "object",
|
|
590
663
|
"description": "Status line visibility toggles for the AI card footer.",
|
|
591
664
|
"additionalProperties": false,
|
|
592
|
-
"default": {
|
|
665
|
+
"default": {
|
|
666
|
+
"model": true,
|
|
667
|
+
"effort": true,
|
|
668
|
+
"agent": true,
|
|
669
|
+
"taskTime": false,
|
|
670
|
+
"tokens": false,
|
|
671
|
+
"dapiUsage": false
|
|
672
|
+
},
|
|
593
673
|
"properties": {
|
|
594
674
|
"model": {
|
|
595
675
|
"type": "boolean",
|
|
@@ -622,6 +702,54 @@
|
|
|
622
702
|
"description": "Show DingTalk API call count in AI card status line footer."
|
|
623
703
|
}
|
|
624
704
|
}
|
|
705
|
+
},
|
|
706
|
+
"gatewayCapabilities": {
|
|
707
|
+
"type": "object",
|
|
708
|
+
"additionalProperties": false,
|
|
709
|
+
"description": "Account-level capability gates for docs and proactive-send Gateway RPCs. Merged with the channel-level gatewayCapabilities by sub-key (tools / docs / send), so a channel-level allowlist is never dropped implicitly.",
|
|
710
|
+
"properties": {
|
|
711
|
+
"tools": {
|
|
712
|
+
"type": "object",
|
|
713
|
+
"additionalProperties": false,
|
|
714
|
+
"description": "Capability switches. Omitted switches default to enabled.",
|
|
715
|
+
"properties": {
|
|
716
|
+
"docs": {
|
|
717
|
+
"type": "boolean",
|
|
718
|
+
"description": "Enable dingtalk.docs.* and dingtalk-connector.docs.* Gateway RPCs. Defaults to true when omitted."
|
|
719
|
+
},
|
|
720
|
+
"proactiveSend": {
|
|
721
|
+
"type": "boolean",
|
|
722
|
+
"description": "Enable dingtalk-connector.sendToUser/sendToGroup/send proactive-send RPCs. Defaults to true when omitted."
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
"docs": {
|
|
727
|
+
"type": "object",
|
|
728
|
+
"additionalProperties": false,
|
|
729
|
+
"description": "Docs RPC allowlist. When allowedSpaceIds is configured, requests without a spaceId (for example dingtalk.docs.append) are denied as well.",
|
|
730
|
+
"properties": {
|
|
731
|
+
"allowedSpaceIds": {
|
|
732
|
+
"type": "array",
|
|
733
|
+
"minItems": 1,
|
|
734
|
+
"items": { "type": "string", "minLength": 1 },
|
|
735
|
+
"description": "When set, docs RPCs only accept these spaceId values."
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
"send": {
|
|
740
|
+
"type": "object",
|
|
741
|
+
"additionalProperties": false,
|
|
742
|
+
"description": "Proactive-send target allowlist.",
|
|
743
|
+
"properties": {
|
|
744
|
+
"allowedTargets": {
|
|
745
|
+
"type": "array",
|
|
746
|
+
"minItems": 1,
|
|
747
|
+
"items": { "type": "string", "pattern": "^(user|group):\\S+$" },
|
|
748
|
+
"description": "When set, proactive-send RPCs only accept these user:<id> or group:<conversationId> targets."
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
625
753
|
}
|
|
626
754
|
}
|
|
627
755
|
}
|
|
@@ -778,6 +906,14 @@
|
|
|
778
906
|
"label": "Card Stream Interval (ms)",
|
|
779
907
|
"help": "Throttle interval in milliseconds between AI card incremental updates."
|
|
780
908
|
},
|
|
909
|
+
"cardTaskProgress": {
|
|
910
|
+
"label": "Card Task Progress",
|
|
911
|
+
"help": "Show a live task-progress block on AI cards for long-running tasks. Leave empty to keep the default (on unless cardStreamingMode is explicitly off)."
|
|
912
|
+
},
|
|
913
|
+
"cardTaskProgressRefresh": {
|
|
914
|
+
"label": "Card Task Progress Refresh",
|
|
915
|
+
"help": "heartbeat (default) refreshes the progress block every 30 seconds with a predictable update count; interval also pushes every tool-driven stage change, throttled by cardStreamInterval."
|
|
916
|
+
},
|
|
781
917
|
"aicardDegradeMs": {
|
|
782
918
|
"label": "AI Card Degrade Window (ms)",
|
|
783
919
|
"help": "Cooldown window after AI card trigger errors. Replies fall back to non-card delivery during this period."
|
|
@@ -838,6 +974,26 @@
|
|
|
838
974
|
"label": "Legacy Async Mode",
|
|
839
975
|
"help": "Deprecated compatibility field from older host or runtime integrations. The current runtime ignores it."
|
|
840
976
|
},
|
|
977
|
+
"gatewayCapabilities": {
|
|
978
|
+
"label": "Gateway RPC Capability Gates",
|
|
979
|
+
"help": "Turn docs and proactive-send Gateway RPCs off, or restrict them to specific doc spaces and send targets."
|
|
980
|
+
},
|
|
981
|
+
"gatewayCapabilities.tools.docs": {
|
|
982
|
+
"label": "Docs RPC Enabled",
|
|
983
|
+
"help": "Allow dingtalk.docs.* and dingtalk-connector.docs.* Gateway RPCs. Defaults to enabled."
|
|
984
|
+
},
|
|
985
|
+
"gatewayCapabilities.tools.proactiveSend": {
|
|
986
|
+
"label": "Proactive Send RPC Enabled",
|
|
987
|
+
"help": "Allow dingtalk-connector.sendToUser/sendToGroup/send Gateway RPCs. Defaults to enabled."
|
|
988
|
+
},
|
|
989
|
+
"gatewayCapabilities.docs.allowedSpaceIds": {
|
|
990
|
+
"label": "Allowed Doc Space IDs",
|
|
991
|
+
"help": "When set, docs RPCs only accept these spaceId values; requests without a spaceId, such as dingtalk.docs.append, are denied."
|
|
992
|
+
},
|
|
993
|
+
"gatewayCapabilities.send.allowedTargets": {
|
|
994
|
+
"label": "Allowed Send Targets",
|
|
995
|
+
"help": "When set, proactive-send RPCs only accept these user:<id> or group:<conversationId> targets."
|
|
996
|
+
},
|
|
841
997
|
"accounts": {
|
|
842
998
|
"label": "Named Accounts",
|
|
843
999
|
"help": "Create named DingTalk accounts when one plugin instance must serve multiple apps or tenants."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soimy/dingtalk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "DingTalk (钉钉) channel plugin for OpenClaw",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bot",
|
|
@@ -29,10 +29,6 @@
|
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
31
|
"type": "module",
|
|
32
|
-
"engines": {
|
|
33
|
-
"node": ">=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0"
|
|
34
|
-
},
|
|
35
|
-
"packageManager": "pnpm@10.33.0",
|
|
36
32
|
"main": "./dist/index.js",
|
|
37
33
|
"types": "./dist/index.d.ts",
|
|
38
34
|
"exports": {
|
|
@@ -49,14 +45,14 @@
|
|
|
49
45
|
"build": "pnpm run build:runtime && pnpm run build:types",
|
|
50
46
|
"build:runtime": "node scripts/build-runtime.mjs",
|
|
51
47
|
"build:types": "tsc -p tsconfig.build.json",
|
|
52
|
-
"format": "oxfmt --write package.json tsconfig.json index.ts src/*.ts",
|
|
53
|
-
"format:check": "oxfmt --check package.json tsconfig.json index.ts src/*.ts",
|
|
54
|
-
"lint": "oxlint --type-aware index.ts src",
|
|
55
|
-
"lint:fix": "oxlint --type-aware --fix index.ts src && pnpm format",
|
|
56
|
-
"docs:dev": "vitepress dev docs --host 127.0.0.1 --port 8000",
|
|
57
|
-
"docs:serv": "vitepress dev docs --host 127.0.0.1 --port 8000",
|
|
58
48
|
"docs:build": "vitepress build docs",
|
|
49
|
+
"docs:dev": "vitepress dev docs --host 127.0.0.1 --port 8000",
|
|
59
50
|
"docs:preview": "vitepress preview docs --host 127.0.0.1 --port 4173",
|
|
51
|
+
"docs:serv": "vitepress dev docs --host 127.0.0.1 --port 8000",
|
|
52
|
+
"format": "oxfmt --write package.json tsconfig.json openclaw.plugin.json vitest.config.ts index.ts \"src/**/*.ts\" \"scripts/**/*.mjs\"",
|
|
53
|
+
"format:check": "oxfmt --check package.json tsconfig.json openclaw.plugin.json vitest.config.ts index.ts \"src/**/*.ts\" \"scripts/**/*.mjs\"",
|
|
54
|
+
"lint": "oxlint --type-aware index.ts src",
|
|
55
|
+
"lint:fix": "oxlint --type-aware --fix index.ts src && pnpm format",
|
|
60
56
|
"monitor:stream": "node scripts/dingtalk-stream-monitor.mjs",
|
|
61
57
|
"pack:check": "node scripts/verify-runtime-package.mjs",
|
|
62
58
|
"prepack": "pnpm run build",
|
|
@@ -76,7 +72,7 @@
|
|
|
76
72
|
"@types/node": "^25.2.0",
|
|
77
73
|
"@vitest/coverage-v8": "^3.2.4",
|
|
78
74
|
"esbuild": "^0.27.3",
|
|
79
|
-
"openclaw": "2026.
|
|
75
|
+
"openclaw": "2026.8.1",
|
|
80
76
|
"oxfmt": "0.34.0",
|
|
81
77
|
"oxlint": "1.49.0",
|
|
82
78
|
"oxlint-tsgolint": "0.18.1",
|
|
@@ -85,19 +81,23 @@
|
|
|
85
81
|
"vitest": "^3.2.4"
|
|
86
82
|
},
|
|
87
83
|
"peerDependencies": {
|
|
88
|
-
"openclaw": ">=2026.
|
|
84
|
+
"openclaw": ">=2026.8.1"
|
|
89
85
|
},
|
|
90
86
|
"peerDependenciesMeta": {
|
|
91
87
|
"openclaw": {
|
|
92
88
|
"optional": true
|
|
93
89
|
}
|
|
94
90
|
},
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": ">=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0"
|
|
93
|
+
},
|
|
94
|
+
"packageManager": "pnpm@10.33.0",
|
|
95
95
|
"openclaw": {
|
|
96
96
|
"compat": {
|
|
97
|
-
"pluginApi": ">=2026.
|
|
97
|
+
"pluginApi": ">=2026.8.1"
|
|
98
98
|
},
|
|
99
99
|
"build": {
|
|
100
|
-
"openclawVersion": "2026.
|
|
100
|
+
"openclawVersion": "2026.8.1"
|
|
101
101
|
},
|
|
102
102
|
"extensions": [
|
|
103
103
|
"./index.ts"
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
]
|
|
124
124
|
},
|
|
125
125
|
"install": {
|
|
126
|
-
"minHostVersion": ">=2026.
|
|
126
|
+
"minHostVersion": ">=2026.8.1",
|
|
127
127
|
"npmSpec": "@soimy/dingtalk",
|
|
128
128
|
"localPath": ".",
|
|
129
129
|
"defaultChoice": "npm"
|
|
@@ -10,10 +10,70 @@ type EmojiMap = Record<SentenceType, readonly string[]>;
|
|
|
10
10
|
const CATCHPHRASE = "叽 ";
|
|
11
11
|
|
|
12
12
|
const KEYWORDS = {
|
|
13
|
-
praise: [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
praise: [
|
|
14
|
+
"真棒",
|
|
15
|
+
"太好了",
|
|
16
|
+
"厉害",
|
|
17
|
+
"优秀",
|
|
18
|
+
"聪明",
|
|
19
|
+
"好样的",
|
|
20
|
+
"赞",
|
|
21
|
+
"牛",
|
|
22
|
+
"完美",
|
|
23
|
+
"出色",
|
|
24
|
+
"真行",
|
|
25
|
+
"干得漂亮",
|
|
26
|
+
"天才",
|
|
27
|
+
"棒极了",
|
|
28
|
+
],
|
|
29
|
+
blame: [
|
|
30
|
+
"怎么又",
|
|
31
|
+
"搞砸",
|
|
32
|
+
"太差了",
|
|
33
|
+
"烦死了",
|
|
34
|
+
"讨厌",
|
|
35
|
+
"笨",
|
|
36
|
+
"蠢",
|
|
37
|
+
"马虎",
|
|
38
|
+
"不负责任",
|
|
39
|
+
"乱来",
|
|
40
|
+
"糟糕",
|
|
41
|
+
"废物",
|
|
42
|
+
"气死我了",
|
|
43
|
+
"错了",
|
|
44
|
+
],
|
|
45
|
+
command: [
|
|
46
|
+
"必须",
|
|
47
|
+
"立刻",
|
|
48
|
+
"马上",
|
|
49
|
+
"赶紧",
|
|
50
|
+
"不准",
|
|
51
|
+
"不要",
|
|
52
|
+
"别动",
|
|
53
|
+
"别说",
|
|
54
|
+
"别做",
|
|
55
|
+
"快去",
|
|
56
|
+
"去做",
|
|
57
|
+
"给我",
|
|
58
|
+
"听着",
|
|
59
|
+
"站住",
|
|
60
|
+
"闭嘴",
|
|
61
|
+
],
|
|
62
|
+
request: [
|
|
63
|
+
"能不能",
|
|
64
|
+
"可以吗",
|
|
65
|
+
"好吗",
|
|
66
|
+
"请",
|
|
67
|
+
"麻烦",
|
|
68
|
+
"帮个忙",
|
|
69
|
+
"帮忙",
|
|
70
|
+
"劳驾",
|
|
71
|
+
"能否",
|
|
72
|
+
"想请你",
|
|
73
|
+
"能帮我",
|
|
74
|
+
"借我",
|
|
75
|
+
"方便吗",
|
|
76
|
+
],
|
|
17
77
|
} as const;
|
|
18
78
|
|
|
19
79
|
const POLITE_EXCLUSIONS = ["别客气", "别介意", "别见怪", "别担心", "别着急"] as const;
|
|
@@ -23,25 +83,34 @@ const EMOJIS: EmojiMap = {
|
|
|
23
83
|
// Keep only the strings that survived repeated direct API retests against
|
|
24
84
|
// the live endpoint using a real message target. Removed as unstable/bad:
|
|
25
85
|
// `٩(๑>◡<๑)۶`.
|
|
26
|
-
|
|
27
|
-
|
|
86
|
+
夸奖: ["(๑•̀ㅂ•́)و✧", "(ノ≧∀≦)ノ", "(★▽★)", "(⌒▽⌒)☆", "(*≧ω≦)", "(ง •_•)ง", "ヾ(≧▽≦*)o"],
|
|
87
|
+
责怪: [
|
|
88
|
+
"(╬ Ò﹏Ó)",
|
|
89
|
+
"(╯°□°)╯",
|
|
90
|
+
"(▼皿▼#)",
|
|
91
|
+
"(。•́︿•̀。)",
|
|
92
|
+
"(╥﹏╥)",
|
|
93
|
+
"ヽ(`Д´)ノ",
|
|
94
|
+
"(#><)",
|
|
95
|
+
"(;′⌒`)",
|
|
96
|
+
],
|
|
28
97
|
// Keep command kaomoji limited to strings that passed local
|
|
29
98
|
// DingTalk emotion/reply verification. Removed as unstable/bad after
|
|
30
99
|
// repeated direct API retests: `┌(┌ *`д´)┐`, `(•̀へ •́ ╮ )`.
|
|
31
|
-
|
|
100
|
+
命令: ["(¬_¬)", "(`ε´)", "(#`Д´)", "(●`∀´●)", "(`д´)", "( ̄ω ̄;)"],
|
|
32
101
|
// Narrative kaomoji must also stay within the subset accepted by
|
|
33
102
|
// DingTalk emotion/reply. Removed as unstable/bad after repeated direct
|
|
34
103
|
// API retests: `(´• ω •`)`.
|
|
35
|
-
|
|
104
|
+
叙事: ["(。・ω・。)", "( ̄▽ ̄)", "(・・?)", "(。_。)", "( ̄ω ̄)", "(´▽`)", "(=_=)"],
|
|
36
105
|
// Request kaomoji must exclude strings that stayed unstable across
|
|
37
106
|
// repeated direct API retests. Removed as unstable/bad:
|
|
38
107
|
// `(づ。◕‿‿◕。)づ`, `(⁄ ⁄•⁄ω⁄•⁄ ⁄)`.
|
|
39
|
-
|
|
40
|
-
|
|
108
|
+
请求: ["(っ´∀`)っ", "(๑•̀ω•́๑)✧", "(p≧w≦q)", "(♡˙︶˙♡)", "(´;ω;`)", "(人•ᴗ•✿)"],
|
|
109
|
+
未知: ["(•̀_•́)", "(;一_一)", "(???)"],
|
|
41
110
|
};
|
|
42
111
|
|
|
43
112
|
function containsAny(text: string, words: readonly string[]): boolean {
|
|
44
|
-
return words.some(word => text.includes(word));
|
|
113
|
+
return words.some((word) => text.includes(word));
|
|
45
114
|
}
|
|
46
115
|
|
|
47
116
|
export function classifyAckReactionEmoji(sentence: unknown): AckReactionClassifyResult {
|
|
@@ -50,7 +119,7 @@ export function classifyAckReactionEmoji(sentence: unknown): AckReactionClassify
|
|
|
50
119
|
}
|
|
51
120
|
|
|
52
121
|
const s = sentence.trim();
|
|
53
|
-
const isPolitePhrase = POLITE_EXCLUSIONS.some(phrase => s.includes(phrase));
|
|
122
|
+
const isPolitePhrase = POLITE_EXCLUSIONS.some((phrase) => s.includes(phrase));
|
|
54
123
|
const isQuestion = /吗|呢|?|\?/.test(s);
|
|
55
124
|
const startsWithPlease = s.startsWith("请");
|
|
56
125
|
const hasExclamation = /[!!]/.test(s);
|
|
@@ -63,7 +132,10 @@ export function classifyAckReactionEmoji(sentence: unknown): AckReactionClassify
|
|
|
63
132
|
type = "命令";
|
|
64
133
|
} else if (containsAny(s, KEYWORDS.praise)) {
|
|
65
134
|
type = "夸奖";
|
|
66
|
-
} else if (
|
|
135
|
+
} else if (
|
|
136
|
+
containsAny(s, KEYWORDS.blame) ||
|
|
137
|
+
(hasExclamation && /烦|讨厌|笨|蠢|差|气死/.test(s))
|
|
138
|
+
) {
|
|
67
139
|
type = "责怪";
|
|
68
140
|
} else {
|
|
69
141
|
type = "叙事";
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { getAccessToken } from "../platform/auth";
|
|
2
|
+
import type { DingTalkConfig } from "../platform/types";
|
|
3
|
+
import axios from "../shared/http-client";
|
|
4
|
+
import {
|
|
5
|
+
formatDingTalkErrorPayloadLog,
|
|
6
|
+
getErrorMessage,
|
|
7
|
+
getProxyBypassOption,
|
|
8
|
+
} from "../shared/utils";
|
|
5
9
|
|
|
6
10
|
// DingTalk currently exposes a dedicated native "thinking" reaction flow rather than
|
|
7
11
|
// a generic arbitrary-emoji reaction API for this plugin path.
|
|
@@ -114,7 +118,9 @@ function isRetryableEmotionApiError(err: unknown): boolean {
|
|
|
114
118
|
const response = asRecord(asRecord(err)?.response);
|
|
115
119
|
const data = asRecord(response?.data);
|
|
116
120
|
const status = Number(response?.status ?? 0);
|
|
117
|
-
const errorCode = String(data?.code || "")
|
|
121
|
+
const errorCode = String(data?.code || "")
|
|
122
|
+
.trim()
|
|
123
|
+
.toLowerCase();
|
|
118
124
|
if (!response) {
|
|
119
125
|
return true;
|
|
120
126
|
}
|
|
@@ -136,7 +142,7 @@ export async function attachNativeAckReaction(
|
|
|
136
142
|
for (let index = 0; index < THINKING_REACTION_ATTACH_DELAYS_MS.length; index += 1) {
|
|
137
143
|
const delayMs = THINKING_REACTION_ATTACH_DELAYS_MS[index];
|
|
138
144
|
if (delayMs > 0) {
|
|
139
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
145
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
140
146
|
}
|
|
141
147
|
const attempt = index + 1;
|
|
142
148
|
const attemptLabel = `${attempt}/${THINKING_REACTION_ATTACH_DELAYS_MS.length}`;
|
|
@@ -191,7 +197,7 @@ export async function recallNativeAckReactionWithRetry(
|
|
|
191
197
|
}
|
|
192
198
|
for (const delayMs of THINKING_REACTION_RECALL_DELAYS_MS) {
|
|
193
199
|
if (delayMs > 0) {
|
|
194
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
200
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
195
201
|
}
|
|
196
202
|
if (await recallNativeAckReaction(config, request, log)) {
|
|
197
203
|
return;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { attachNativeAckReaction, recallNativeAckReactionWithRetry } from "../ack-reaction-service";
|
|
2
|
-
import type { DingTalkConfig } from "../types";
|
|
3
|
-
import { getErrorMessage } from "../utils";
|
|
4
1
|
import {
|
|
5
|
-
|
|
2
|
+
createAgentEventCorrelator,
|
|
6
3
|
describeEvent,
|
|
7
|
-
type DynamicAckReactionLogger,
|
|
8
4
|
type RuntimeAgentEvent,
|
|
5
|
+
type RuntimeEventsLogger,
|
|
9
6
|
type RuntimeEventsSurface,
|
|
10
|
-
} from "
|
|
7
|
+
} from "../platform/runtime-events";
|
|
8
|
+
import type { DingTalkConfig } from "../platform/types";
|
|
9
|
+
import { getErrorMessage } from "../shared/utils";
|
|
10
|
+
import { attachNativeAckReaction, recallNativeAckReactionWithRetry } from "./ack-reaction-service";
|
|
11
11
|
import { resolveToolProgressReaction } from "./dynamic-ack-reaction-progress";
|
|
12
12
|
|
|
13
|
+
const CORRELATION_CONSUMER = "ack-reaction";
|
|
14
|
+
|
|
13
15
|
type DynamicAckReactionControllerParams = {
|
|
14
16
|
enabled: boolean;
|
|
15
17
|
initialReaction: string;
|
|
@@ -19,7 +21,7 @@ type DynamicAckReactionControllerParams = {
|
|
|
19
21
|
msgId: string;
|
|
20
22
|
conversationId: string;
|
|
21
23
|
sessionKey: string;
|
|
22
|
-
log?:
|
|
24
|
+
log?: RuntimeEventsLogger;
|
|
23
25
|
runtimeEvents?: RuntimeEventsSurface;
|
|
24
26
|
onReactionDisposed?: () => void;
|
|
25
27
|
};
|
|
@@ -42,7 +44,8 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
42
44
|
let lastDynamicReactionSwitchAt = 0;
|
|
43
45
|
let disposed = false;
|
|
44
46
|
const createdAt = Date.now();
|
|
45
|
-
const isCorrelatedEvent =
|
|
47
|
+
const isCorrelatedEvent = createAgentEventCorrelator({
|
|
48
|
+
consumer: CORRELATION_CONSUMER,
|
|
46
49
|
sessionKey: params.sessionKey,
|
|
47
50
|
enabled: params.enabled,
|
|
48
51
|
createdAt,
|
|
@@ -55,7 +58,7 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
55
58
|
if (disposed || !normalizedReaction || !params.enabled || !ackReactionAttached) {
|
|
56
59
|
params.log?.debug?.(
|
|
57
60
|
`[DingTalk] Dynamic ack reaction update skipped reaction=${normalizedReaction || "-"} ` +
|
|
58
|
-
|
|
61
|
+
`enabled=${params.enabled} ackReactionAttached=${ackReactionAttached} disposed=${disposed}`,
|
|
59
62
|
);
|
|
60
63
|
return;
|
|
61
64
|
}
|
|
@@ -70,12 +73,12 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
70
73
|
return;
|
|
71
74
|
}
|
|
72
75
|
if (
|
|
73
|
-
lastDynamicReactionSwitchAt > 0
|
|
74
|
-
|
|
76
|
+
lastDynamicReactionSwitchAt > 0 &&
|
|
77
|
+
Date.now() - lastDynamicReactionSwitchAt < DYNAMIC_REACTION_MIN_SWITCH_INTERVAL_MS
|
|
75
78
|
) {
|
|
76
79
|
params.log?.debug?.(
|
|
77
80
|
`[DingTalk] Dynamic ack reaction update throttled previous=${currentAckReaction} next=${normalizedReaction} ` +
|
|
78
|
-
|
|
81
|
+
`minIntervalMs=${DYNAMIC_REACTION_MIN_SWITCH_INTERVAL_MS}`,
|
|
79
82
|
);
|
|
80
83
|
return;
|
|
81
84
|
}
|
|
@@ -150,7 +153,9 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
150
153
|
dynamicReactionUpdatePromise = dynamicReactionUpdatePromise
|
|
151
154
|
.then(() => updateDynamicAckReaction(nextReaction))
|
|
152
155
|
.catch((err: unknown) => {
|
|
153
|
-
params.log?.warn?.(
|
|
156
|
+
params.log?.warn?.(
|
|
157
|
+
`[DingTalk] Dynamic ack reaction update failed: ${getErrorMessage(err)}`,
|
|
158
|
+
);
|
|
154
159
|
});
|
|
155
160
|
return dynamicReactionUpdatePromise;
|
|
156
161
|
};
|
|
@@ -160,7 +165,9 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
160
165
|
if (!params.enabled || disposed) {
|
|
161
166
|
return;
|
|
162
167
|
}
|
|
163
|
-
params.log?.debug?.(
|
|
168
|
+
params.log?.debug?.(
|
|
169
|
+
`[DingTalk] Dynamic reaction observed agent event ${describeEvent(agentEvent)}`,
|
|
170
|
+
);
|
|
164
171
|
if (agentEvent?.stream === "lifecycle" && agentEvent.data?.phase === "start") {
|
|
165
172
|
void isCorrelatedEvent(agentEvent);
|
|
166
173
|
return;
|
|
@@ -174,7 +181,8 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
174
181
|
);
|
|
175
182
|
return;
|
|
176
183
|
}
|
|
177
|
-
const toolCallId =
|
|
184
|
+
const toolCallId =
|
|
185
|
+
typeof agentEvent.data?.toolCallId === "string" ? agentEvent.data.toolCallId : "-";
|
|
178
186
|
params.log?.debug?.(
|
|
179
187
|
`[DingTalk] Tool event received for dynamic ack reaction: name=${agentEvent.data?.name || "-"} toolCallId=${toolCallId}`,
|
|
180
188
|
);
|
|
@@ -183,26 +191,31 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
183
191
|
);
|
|
184
192
|
};
|
|
185
193
|
|
|
186
|
-
const unsubscribeAgentEvents =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
const unsubscribeAgentEvents =
|
|
195
|
+
params.enabled && params.runtimeEvents?.onAgentEvent
|
|
196
|
+
? params.runtimeEvents.onAgentEvent((event: unknown) => {
|
|
197
|
+
void handleAgentEvent(event).catch((err: unknown) => {
|
|
198
|
+
params.log?.warn?.(
|
|
199
|
+
`[DingTalk] Dynamic ack reaction event handling failed: ${getErrorMessage(err)}`,
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
})
|
|
203
|
+
: () => {};
|
|
193
204
|
|
|
194
205
|
if (params.enabled && !params.runtimeEvents?.onAgentEvent) {
|
|
195
|
-
params.log?.debug?.(
|
|
206
|
+
params.log?.debug?.(
|
|
207
|
+
"[DingTalk] onAgentEvent not available, dynamic reaction tracking disabled",
|
|
208
|
+
);
|
|
196
209
|
}
|
|
197
210
|
|
|
198
211
|
if (params.enabled) {
|
|
199
212
|
progressHeartbeatTimer = setInterval(() => {
|
|
200
213
|
if (
|
|
201
|
-
disposed
|
|
202
|
-
|
|
203
|
-
||
|
|
204
|
-
|
|
205
|
-
|
|
214
|
+
disposed ||
|
|
215
|
+
!ackReactionAttached ||
|
|
216
|
+
progressHeartbeatInFlight ||
|
|
217
|
+
dynamicReactionStartedAt === 0 ||
|
|
218
|
+
lastDynamicReactionAt === 0
|
|
206
219
|
) {
|
|
207
220
|
return;
|
|
208
221
|
}
|
|
@@ -211,7 +224,7 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
211
224
|
}
|
|
212
225
|
params.log?.debug?.(
|
|
213
226
|
`[DingTalk] Dynamic ack reaction heartbeat triggered currentReaction=${currentAckReaction} ` +
|
|
214
|
-
|
|
227
|
+
`lastDynamicReactionAt=${lastDynamicReactionAt}`,
|
|
215
228
|
);
|
|
216
229
|
progressHeartbeatInFlight = true;
|
|
217
230
|
void queueDynamicAckReactionUpdate(TOOL_HEARTBEAT_REACTION).finally(() => {
|
|
@@ -248,7 +261,7 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
248
261
|
const elapsedMs = ackReactionAttachedAt > 0 ? Date.now() - ackReactionAttachedAt : 0;
|
|
249
262
|
const remainingVisibleMs = shouldRespectMinVisible ? minVisibleMs - elapsedMs : 0;
|
|
250
263
|
if (remainingVisibleMs > 0) {
|
|
251
|
-
await new Promise(resolve => setTimeout(resolve, remainingVisibleMs));
|
|
264
|
+
await new Promise((resolve) => setTimeout(resolve, remainingVisibleMs));
|
|
252
265
|
}
|
|
253
266
|
await recallNativeAckReactionWithRetry(
|
|
254
267
|
params.dingtalkConfig,
|
|
@@ -260,7 +273,9 @@ export function createDynamicAckReactionController(params: DynamicAckReactionCon
|
|
|
260
273
|
params.log,
|
|
261
274
|
);
|
|
262
275
|
} catch (err: unknown) {
|
|
263
|
-
params.log?.warn?.(
|
|
276
|
+
params.log?.warn?.(
|
|
277
|
+
`[DingTalk] Dynamic ack reaction dispose recall failed: ${getErrorMessage(err)}`,
|
|
278
|
+
);
|
|
264
279
|
} finally {
|
|
265
280
|
ackReactionAttached = false;
|
|
266
281
|
params.onReactionDisposed?.();
|
|
@@ -27,7 +27,10 @@ export function resolveToolProgressReaction(toolName: unknown, args: unknown): s
|
|
|
27
27
|
if (!command) {
|
|
28
28
|
return "🛠️";
|
|
29
29
|
}
|
|
30
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
/\bbrew\s+install\s+/i.test(command) ||
|
|
32
|
+
/\b(?:pnpm|npm|yarn)\s+(?:add|install)\s+/i.test(command)
|
|
33
|
+
) {
|
|
31
34
|
return "📦";
|
|
32
35
|
}
|
|
33
36
|
if (/\bwhich\s+/i.test(command)) {
|