@fastagent-sh/fastagent 0.21.1 → 0.22.1
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 +9 -12
- package/dist/agent.d.ts +24 -37
- package/dist/agent.js +7 -15
- package/dist/atomic-write.d.ts +13 -17
- package/dist/atomic-write.js +18 -29
- package/dist/bind.d.ts +12 -22
- package/dist/bind.js +18 -27
- package/dist/channel.d.ts +11 -33
- package/dist/channels/agentcore-limits.d.ts +2 -13
- package/dist/channels/agentcore-limits.js +2 -13
- package/dist/channels/agentcore-protocol.d.ts +67 -58
- package/dist/channels/agentcore-protocol.js +23 -15
- package/dist/channels/agentcore-service.d.ts +19 -33
- package/dist/channels/agentcore-service.js +176 -59
- package/dist/channels/agentcore.d.ts +39 -33
- package/dist/channels/agentcore.js +90 -224
- package/dist/channels/body.d.ts +15 -2
- package/dist/channels/body.js +24 -2
- package/dist/channels/busy.d.ts +1 -21
- package/dist/channels/busy.js +2 -39
- package/dist/channels/control.d.ts +17 -62
- package/dist/channels/control.js +74 -182
- package/dist/channels/define-channel.d.ts +39 -0
- package/dist/channels/define-channel.js +9 -0
- package/dist/channels/discover.d.ts +10 -31
- package/dist/channels/discover.js +37 -31
- package/dist/channels/feishu/bootstrap-token.d.ts +1 -8
- package/dist/channels/feishu/bootstrap-token.js +7 -23
- package/dist/channels/feishu/card.d.ts +14 -28
- package/dist/channels/feishu/card.js +16 -30
- package/dist/channels/feishu/cloud.d.ts +1 -5
- package/dist/channels/feishu/context-buffer.d.ts +4 -23
- package/dist/channels/feishu/context-buffer.js +8 -31
- package/dist/channels/feishu/crypto.d.ts +10 -5
- package/dist/channels/feishu/crypto.js +12 -19
- package/dist/channels/feishu/feishu-api.d.ts +2 -1
- package/dist/channels/feishu/feishu-api.js +5 -4
- package/dist/channels/feishu/feishu.d.ts +4 -10
- package/dist/channels/feishu/feishu.js +113 -227
- package/dist/channels/feishu/invoke-turn.d.ts +5 -4
- package/dist/channels/feishu/invoke-turn.js +36 -54
- package/dist/channels/feishu/model.d.ts +4 -21
- package/dist/channels/feishu/model.js +1 -8
- package/dist/channels/feishu/normalize.d.ts +2 -10
- package/dist/channels/feishu/normalize.js +7 -42
- package/dist/channels/feishu/parse.d.ts +9 -29
- package/dist/channels/feishu/parse.js +8 -26
- package/dist/channels/feishu/preview.d.ts +12 -14
- package/dist/channels/feishu/preview.js +108 -207
- package/dist/channels/feishu/register-app.d.ts +8 -23
- package/dist/channels/feishu/register-app.js +7 -20
- package/dist/channels/feishu/register-webhook.d.ts +2 -9
- package/dist/channels/feishu/register-webhook.js +9 -33
- package/dist/channels/feishu/scaffold/channel.ts +27 -19
- package/dist/channels/feishu/scaffold/channel.websocket.ts +31 -0
- package/dist/channels/feishu/setup-mode.d.ts +11 -36
- package/dist/channels/feishu/setup-mode.js +7 -26
- package/dist/channels/feishu/ws-ingress.d.ts +1 -2
- package/dist/channels/feishu/ws-ingress.js +6 -8
- package/dist/channels/http.d.ts +15 -15
- package/dist/channels/http.js +19 -9
- package/dist/channels/kit/attachment-path.d.ts +4 -5
- package/dist/channels/kit/attachment-path.js +10 -34
- package/dist/channels/kit/context-buffer.d.ts +14 -21
- package/dist/channels/kit/context-buffer.js +25 -38
- package/dist/channels/kit/delivery.d.ts +35 -0
- package/dist/channels/kit/delivery.js +129 -0
- package/dist/channels/kit/event-stream.d.ts +5 -0
- package/dist/channels/kit/event-stream.js +29 -0
- package/dist/channels/kit/invoke-turn-kit.d.ts +53 -26
- package/dist/channels/kit/invoke-turn-kit.js +89 -32
- package/dist/channels/kit/preview-kit.d.ts +18 -72
- package/dist/channels/kit/preview-kit.js +22 -88
- package/dist/channels/kit/signature.d.ts +3 -9
- package/dist/channels/kit/signature.js +3 -9
- package/dist/channels/kit/state.d.ts +1 -2
- package/dist/channels/kit/state.js +5 -14
- package/dist/channels/kit/stop-command.d.ts +1 -2
- package/dist/channels/kit/stop-command.js +6 -9
- package/dist/channels/kit/tasks.d.ts +1 -1
- package/dist/channels/kit/tasks.js +8 -21
- package/dist/channels/kit/text.d.ts +2 -16
- package/dist/channels/kit/text.js +23 -31
- package/dist/channels/kit/thread-participants.d.ts +4 -17
- package/dist/channels/kit/thread-participants.js +8 -55
- package/dist/channels/kit/transport.d.ts +26 -0
- package/dist/channels/kit/transport.js +20 -0
- package/dist/channels/kit/turn-queue.d.ts +7 -11
- package/dist/channels/kit/turn-queue.js +21 -39
- package/dist/channels/kit/turn-runner.d.ts +32 -18
- package/dist/channels/kit/turn-runner.js +98 -53
- package/dist/channels/kit/turn-store.d.ts +32 -32
- package/dist/channels/kit/turn-store.js +45 -88
- package/dist/channels/lark/lark.d.ts +1 -5
- package/dist/channels/lark/onboard.d.ts +3 -12
- package/dist/channels/lark/onboard.js +3 -13
- package/dist/channels/lark/scaffold/channel.ts +27 -19
- package/dist/channels/lark/scaffold/channel.websocket.ts +31 -0
- package/dist/channels/registration.d.ts +9 -35
- package/dist/channels/registration.js +6 -37
- package/dist/channels/secret.js +2 -5
- package/dist/channels/serve.d.ts +47 -44
- package/dist/channels/serve.js +165 -101
- package/dist/channels/slack/config-api.d.ts +4 -27
- package/dist/channels/slack/config-api.js +5 -34
- package/dist/channels/slack/context-buffer.d.ts +2 -3
- package/dist/channels/slack/context-buffer.js +5 -5
- package/dist/channels/slack/invoke-turn.d.ts +3 -1
- package/dist/channels/slack/invoke-turn.js +25 -34
- package/dist/channels/slack/manifest.js +1 -3
- package/dist/channels/slack/model.d.ts +1 -2
- package/dist/channels/slack/model.js +1 -1
- package/dist/channels/slack/onboard.d.ts +4 -3
- package/dist/channels/slack/onboard.js +8 -11
- package/dist/channels/slack/onboarding-state.d.ts +3 -5
- package/dist/channels/slack/onboarding-state.js +9 -6
- package/dist/channels/slack/parse.d.ts +4 -13
- package/dist/channels/slack/parse.js +7 -28
- package/dist/channels/slack/preview.d.ts +12 -2
- package/dist/channels/slack/preview.js +292 -269
- package/dist/channels/slack/reaction.d.ts +11 -3
- package/dist/channels/slack/reaction.js +19 -8
- package/dist/channels/slack/register-webhook.js +4 -7
- package/dist/channels/slack/scaffold/channel.ts +20 -13
- package/dist/channels/slack/scaffold/slack-send.ts +2 -2
- package/dist/channels/slack/setup-server.d.ts +1 -5
- package/dist/channels/slack/setup-server.js +1 -5
- package/dist/channels/slack/shared-api.d.ts +1 -4
- package/dist/channels/slack/shared-api.js +2 -13
- package/dist/channels/slack/slack-api.d.ts +2 -1
- package/dist/channels/slack/slack-api.js +6 -4
- package/dist/channels/slack/slack.d.ts +11 -14
- package/dist/channels/slack/slack.js +121 -122
- package/dist/channels/sse.d.ts +1 -1
- package/dist/channels/sse.js +1 -1
- package/dist/channels/telegram/context-buffer.d.ts +7 -22
- package/dist/channels/telegram/context-buffer.js +6 -23
- package/dist/channels/telegram/invoke-turn.d.ts +7 -7
- package/dist/channels/telegram/invoke-turn.js +24 -43
- package/dist/channels/telegram/parse.d.ts +24 -51
- package/dist/channels/telegram/parse.js +32 -84
- package/dist/channels/telegram/preview.d.ts +10 -1
- package/dist/channels/telegram/preview.js +79 -100
- package/dist/channels/telegram/register-webhook.js +5 -23
- package/dist/channels/telegram/scaffold/channel.ts +25 -18
- package/dist/channels/telegram/scaffold/telegram-send.ts +6 -4
- package/dist/channels/telegram/telegram-api.d.ts +4 -3
- package/dist/channels/telegram/telegram-api.js +9 -7
- package/dist/channels/telegram/telegram.d.ts +4 -18
- package/dist/channels/telegram/telegram.js +38 -94
- package/dist/channels/telegram/turn-store.d.ts +11 -14
- package/dist/channels/telegram/turn-store.js +8 -6
- package/dist/channels/wait-health.d.ts +4 -6
- package/dist/channels/wait-health.js +10 -14
- package/dist/cli/add-feishu.d.ts +2 -12
- package/dist/cli/add-feishu.js +24 -71
- package/dist/cli/add-slack.d.ts +5 -3
- package/dist/cli/add-slack.js +53 -76
- package/dist/cli/auth-view.d.ts +2 -16
- package/dist/cli/auth-view.js +2 -16
- package/dist/cli/commands/add.js +25 -40
- package/dist/cli/commands/chat.d.ts +0 -1
- package/dist/cli/commands/chat.js +5 -6
- package/dist/cli/commands/deploy/agentcore.js +60 -65
- package/dist/cli/commands/deploy/docker.js +50 -23
- package/dist/cli/commands/deploy/fly.js +23 -61
- package/dist/cli/commands/deploy/railway.js +23 -18
- package/dist/cli/commands/deploy/shared.d.ts +38 -57
- package/dist/cli/commands/deploy/shared.js +40 -59
- package/dist/cli/commands/deploy.d.ts +10 -27
- package/dist/cli/commands/deploy.js +38 -60
- package/dist/cli/commands/destroy.d.ts +4 -0
- package/dist/cli/commands/destroy.js +56 -0
- package/dist/cli/commands/dev.d.ts +2 -1
- package/dist/cli/commands/dev.js +20 -23
- package/dist/cli/commands/info.d.ts +0 -2
- package/dist/cli/commands/info.js +83 -49
- package/dist/cli/commands/init.d.ts +1 -2
- package/dist/cli/commands/init.js +16 -55
- package/dist/cli/commands/invoke.d.ts +0 -1
- package/dist/cli/commands/invoke.js +5 -7
- package/dist/cli/commands/login.d.ts +2 -1
- package/dist/cli/commands/login.js +33 -38
- package/dist/cli/commands/logs.js +3 -4
- package/dist/cli/commands/models.js +1 -5
- package/dist/cli/commands/routine-run.d.ts +6 -0
- package/dist/cli/commands/routine-run.js +47 -0
- package/dist/cli/commands/routine.d.ts +25 -0
- package/dist/cli/commands/routine.js +122 -0
- package/dist/cli/commands/start.d.ts +31 -3
- package/dist/cli/commands/start.js +131 -81
- package/dist/cli/commands/tool.js +26 -12
- package/dist/cli/fail.d.ts +13 -23
- package/dist/cli/fail.js +20 -23
- package/dist/cli/invoke-stream.d.ts +1 -8
- package/dist/cli/kernel.d.ts +6 -38
- package/dist/cli/kernel.js +14 -77
- package/dist/cli/models-view.d.ts +1 -9
- package/dist/cli/models-view.js +11 -22
- package/dist/cli/program.d.ts +5 -6
- package/dist/cli/program.js +120 -157
- package/dist/cli/serve.d.ts +57 -41
- package/dist/cli/serve.js +94 -121
- package/dist/cli/shared.d.ts +15 -61
- package/dist/cli/shared.js +55 -181
- package/dist/cli.js +1 -8
- package/dist/collect.d.ts +6 -0
- package/dist/collect.js +6 -0
- package/dist/core.d.ts +4 -1
- package/dist/core.js +9 -7
- package/dist/declared-secrets.d.ts +55 -0
- package/dist/declared-secrets.js +88 -0
- package/dist/deploy/agentcore/aws-cli.d.ts +91 -0
- package/dist/deploy/agentcore/aws-cli.js +64 -0
- package/dist/deploy/agentcore/destroy.d.ts +51 -0
- package/dist/deploy/agentcore/destroy.js +273 -0
- package/dist/deploy/agentcore/forwarder.js +28 -79
- package/dist/deploy/agentcore/logs.d.ts +2 -18
- package/dist/deploy/agentcore/logs.js +27 -51
- package/dist/deploy/agentcore/plan.d.ts +85 -105
- package/dist/deploy/agentcore/plan.js +152 -314
- package/dist/deploy/agentcore/run.d.ts +28 -28
- package/dist/deploy/agentcore/run.js +227 -306
- package/dist/deploy/agentcore/zip.d.ts +2 -15
- package/dist/deploy/agentcore/zip.js +3 -17
- package/dist/deploy/build-context.d.ts +21 -0
- package/dist/deploy/build-context.js +137 -0
- package/dist/deploy/channel-ingress.d.ts +26 -39
- package/dist/deploy/channel-ingress.js +57 -28
- package/dist/deploy/container.d.ts +20 -34
- package/dist/deploy/container.js +49 -100
- package/dist/deploy/docker/plan.d.ts +12 -11
- package/dist/deploy/docker/plan.js +43 -24
- package/dist/deploy/docker/run.d.ts +22 -25
- package/dist/deploy/docker/run.js +39 -37
- package/dist/deploy/fly/plan.d.ts +15 -44
- package/dist/deploy/fly/plan.js +41 -73
- package/dist/deploy/fly/run.d.ts +16 -51
- package/dist/deploy/fly/run.js +42 -95
- package/dist/deploy/hosts.d.ts +24 -3
- package/dist/deploy/hosts.js +24 -3
- package/dist/deploy/preflight.d.ts +47 -41
- package/dist/deploy/preflight.js +282 -383
- package/dist/deploy/railway/plan.d.ts +16 -42
- package/dist/deploy/railway/plan.js +42 -60
- package/dist/deploy/railway/run.d.ts +30 -68
- package/dist/deploy/railway/run.js +86 -100
- package/dist/deploy/registration-gate.d.ts +6 -13
- package/dist/deploy/residency.d.ts +37 -0
- package/dist/deploy/residency.js +24 -0
- package/dist/deploy/runner.d.ts +10 -9
- package/dist/deploy/runner.js +7 -18
- package/dist/deploy/secrets.d.ts +40 -41
- package/dist/deploy/secrets.js +117 -103
- package/dist/deploy/workspace.d.ts +50 -0
- package/dist/deploy/workspace.js +197 -0
- package/dist/dev-supervisor.d.ts +1 -9
- package/dist/dev-supervisor.js +21 -64
- package/dist/effect-port.d.ts +50 -0
- package/dist/effect-port.js +77 -0
- package/dist/engines/pi/agent-session-factory.d.ts +50 -69
- package/dist/engines/pi/agent-session-factory.js +249 -146
- package/dist/engines/pi/auth.d.ts +15 -11
- package/dist/engines/pi/auth.js +96 -99
- package/dist/engines/pi/chat.d.ts +1 -5
- package/dist/engines/pi/chat.js +2 -14
- package/dist/engines/pi/config.d.ts +53 -51
- package/dist/engines/pi/config.js +83 -92
- package/dist/engines/pi/create.d.ts +60 -75
- package/dist/engines/pi/create.js +108 -141
- package/dist/engines/pi/definition.d.ts +14 -58
- package/dist/engines/pi/definition.js +21 -85
- package/dist/engines/pi/invoke-session.d.ts +5 -25
- package/dist/engines/pi/invoke-session.js +233 -244
- package/dist/engines/pi/login.d.ts +95 -35
- package/dist/engines/pi/login.js +259 -107
- package/dist/engines/pi/machine.d.ts +31 -0
- package/dist/engines/pi/machine.js +106 -0
- package/dist/engines/pi/models.d.ts +70 -89
- package/dist/engines/pi/models.js +188 -81
- package/dist/engines/pi/open.d.ts +65 -53
- package/dist/engines/pi/open.js +129 -69
- package/dist/engines/pi/report.d.ts +3 -12
- package/dist/engines/pi/report.js +2 -16
- package/dist/engines/pi/search-tools.d.ts +1 -9
- package/dist/engines/pi/search-tools.js +26 -57
- package/dist/engines/pi/service.d.ts +2 -16
- package/dist/engines/pi/service.js +2 -16
- package/dist/engines/pi/session-builder.d.ts +5 -9
- package/dist/engines/pi/session-builder.js +44 -82
- package/dist/engines/pi/session-control.js +286 -269
- package/dist/engines/pi/session-effects.d.ts +14 -0
- package/dist/engines/pi/session-effects.js +30 -0
- package/dist/engines/pi/session-inheritance.d.ts +9 -18
- package/dist/engines/pi/session-inheritance.js +103 -160
- package/dist/engines/pi/session-markers.d.ts +31 -30
- package/dist/engines/pi/session-markers.js +26 -25
- package/dist/engines/pi/session-settings.d.ts +6 -22
- package/dist/engines/pi/session-settings.js +10 -21
- package/dist/engines/pi/session-store.d.ts +26 -92
- package/dist/engines/pi/session-store.js +96 -310
- package/dist/engines/pi/tool-context.d.ts +17 -45
- package/dist/engines/pi/tool-context.js +7 -26
- package/dist/engines/pi/tool.d.ts +45 -36
- package/dist/engines/pi/tool.js +43 -57
- package/dist/engines/pi/turn-kit.d.ts +14 -52
- package/dist/engines/pi/turn-kit.js +18 -67
- package/dist/engines/pi/wake-tool.d.ts +2 -10
- package/dist/engines/pi/wake-tool.js +7 -27
- package/dist/env.d.ts +27 -28
- package/dist/env.js +45 -50
- package/dist/index.js +0 -2
- package/dist/lark.d.ts +1 -2
- package/dist/lark.js +1 -2
- package/dist/loader.d.ts +14 -55
- package/dist/loader.js +24 -43
- package/dist/log.d.ts +2 -12
- package/dist/log.js +3 -24
- package/dist/node.d.ts +2 -15
- package/dist/node.js +2 -18
- package/dist/observe.d.ts +2 -8
- package/dist/open-url.d.ts +1 -1
- package/dist/open-url.js +1 -1
- package/dist/paths.d.ts +70 -134
- package/dist/paths.js +165 -232
- package/dist/pi.d.ts +4 -6
- package/dist/pi.js +3 -3
- package/dist/proxy.d.ts +16 -6
- package/dist/proxy.js +52 -16
- package/dist/runtime.d.ts +18 -12
- package/dist/runtime.js +18 -11
- package/dist/scaffold/add-channel.d.ts +14 -31
- package/dist/scaffold/add-channel.js +48 -112
- package/dist/scaffold/init.d.ts +9 -31
- package/dist/scaffold/init.js +45 -138
- package/dist/scaffold/templates/env.example +6 -4
- package/dist/scaffold/templates/fastagent.config.ts +36 -0
- package/dist/scaffold/templates.d.ts +3 -3
- package/dist/scaffold/templates.js +5 -8
- package/dist/scaffold/vendor-skill.d.ts +2 -5
- package/dist/scaffold/vendor-skill.js +19 -29
- package/dist/schedule/cron.d.ts +9 -5
- package/dist/schedule/cron.js +9 -11
- package/dist/schedule/discover.d.ts +12 -12
- package/dist/schedule/discover.js +43 -34
- package/dist/schedule/routine.d.ts +43 -0
- package/dist/schedule/routine.js +32 -0
- package/dist/schedule/run.d.ts +55 -0
- package/dist/schedule/run.js +146 -0
- package/dist/schedule/scheduler.d.ts +44 -55
- package/dist/schedule/scheduler.js +291 -265
- package/dist/schedule/state.d.ts +105 -10
- package/dist/schedule/state.js +293 -19
- package/dist/schedule/wake-alarm.d.ts +10 -23
- package/dist/schedule/wake-alarm.js +91 -121
- package/dist/schedule/wakeups.d.ts +23 -39
- package/dist/schedule/wakeups.js +33 -75
- package/dist/secrets-gate.d.ts +32 -0
- package/dist/secrets-gate.js +33 -0
- package/dist/service.d.ts +137 -98
- package/dist/service.js +250 -252
- package/dist/session-remote.d.ts +33 -44
- package/dist/session-remote.js +203 -192
- package/dist/session.d.ts +166 -229
- package/dist/session.js +33 -55
- package/dist/tunnel.d.ts +8 -36
- package/dist/tunnel.js +24 -65
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/package.json +10 -16
- package/dist/channels/agentcore-state.d.ts +0 -77
- package/dist/channels/agentcore-state.js +0 -276
- package/dist/channels/github/github.d.ts +0 -31
- package/dist/channels/github/github.js +0 -89
- package/dist/channels/github/scaffold/channel.ts +0 -25
- package/dist/cli/commands/attach.d.ts +0 -108
- package/dist/cli/commands/attach.js +0 -637
- package/dist/cli/commands/fire.d.ts +0 -7
- package/dist/cli/commands/fire.js +0 -38
- package/dist/cli/commands/schedule.d.ts +0 -12
- package/dist/cli/commands/schedule.js +0 -87
- package/dist/github.d.ts +0 -3
- package/dist/github.js +0 -2
- package/dist/scaffold/templates/fastagent.config.mjs +0 -23
- package/dist/schedule/audit.d.ts +0 -18
- package/dist/schedule/audit.js +0 -57
- package/dist/schedule/schedule.d.ts +0 -35
- package/dist/schedule/schedule.js +0 -23
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { log } from "../../log.js";
|
|
2
|
-
import { DEFAULT_BUSY_RETRY, attachedFilesManifest, attributedFileName, backgroundImagesManifest, missingAttachmentsNote,
|
|
2
|
+
import { DEFAULT_BUSY_RETRY, attachedFilesManifest, attributedFileName, backgroundImagesManifest, loadBackground, missingAttachmentsNote, turnStream, } from "../kit/invoke-turn-kit.js";
|
|
3
3
|
import { BUFFER_ATTACH_MAX } from "../kit/context-buffer.js";
|
|
4
4
|
import { parseContent } from "./parse.js";
|
|
5
5
|
import { REFERENT_MAX_CODE_POINTS, truncateCodePointPrefix } from "../kit/text.js";
|
|
@@ -41,9 +41,8 @@ function fetchedSenderLabel(sender, appId) {
|
|
|
41
41
|
* is what makes the walk bounded by STRUCTURE rather than by a level count someone picked.
|
|
42
42
|
*
|
|
43
43
|
* This is pointer resolution, not history. Session memory — what this place already knows — is a
|
|
44
|
-
* different track (design/participant-model.md §8)
|
|
45
|
-
*
|
|
46
|
-
* walks through ANY author's message — the chain is the platform's structure, not a conversation the
|
|
44
|
+
* different track (design/participant-model.md §8), so this walk does only the pointer's job, which is also
|
|
45
|
+
* why it walks through ANY author's message — the chain is the platform's structure, not a conversation the
|
|
47
46
|
* agent took part in. The repetition this implies (an established session re-reads chain text it may
|
|
48
47
|
* already hold, each reply turn) is accepted deliberately and bounded: ancestors are CONTEXT, not
|
|
49
48
|
* the ask, so their text shares ONE further `REFERENT_MAX_CODE_POINTS` budget across the whole chain
|
|
@@ -201,40 +200,25 @@ async function resolveTurnInputs(t, attachments) {
|
|
|
201
200
|
const mergedFiles = capMerge(chain.files, attachments.buffered.files, primaryFiles);
|
|
202
201
|
const bufferedImages = mergedImages.kept;
|
|
203
202
|
const bufferedFiles = mergedFiles.kept;
|
|
204
|
-
const backgroundImages =
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
const fileResults = await Promise.allSettled(bufferedFiles.map(async (ref) => ({
|
|
217
|
-
ref,
|
|
218
|
-
file: await t.api.fetchFile(ref.messageId, ref.key, ref.name ?? ref.key, t.chatId, t.filesDir),
|
|
219
|
-
})));
|
|
220
|
-
for (const result of fileResults) {
|
|
221
|
-
if (result.status === "fulfilled")
|
|
222
|
-
backgroundFiles.push(result.value);
|
|
223
|
-
else {
|
|
224
|
-
lost++;
|
|
225
|
-
log.warn(`${t.label} could not load an earlier (buffered) attachment: ${String(result.reason)}`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const missingNote = missingAttachmentsNote(lost + attachments.buffered.skipped + mergedImages.dropped + mergedFiles.dropped);
|
|
229
|
-
const backgroundImageManifest = backgroundImagesManifest(imageRefs.length, backgroundImages.map(({ ref }) => ref));
|
|
203
|
+
const backgroundImages = await loadBackground(bufferedImages, (ref) => t.api.fetchImage(ref.messageId, ref.key), {
|
|
204
|
+
label: t.label,
|
|
205
|
+
what: "image",
|
|
206
|
+
});
|
|
207
|
+
const backgroundFiles = await loadBackground(bufferedFiles, (ref) => t.api.fetchFile(ref.messageId, ref.key, ref.name ?? ref.key, t.chatId, t.filesDir), { label: t.label, what: "attachment" });
|
|
208
|
+
const missingNote = missingAttachmentsNote(backgroundImages.lost +
|
|
209
|
+
backgroundFiles.lost +
|
|
210
|
+
attachments.buffered.skipped +
|
|
211
|
+
mergedImages.dropped +
|
|
212
|
+
mergedFiles.dropped);
|
|
213
|
+
const backgroundImageManifest = backgroundImagesManifest(imageRefs.length, backgroundImages.loaded.map(({ ref }) => ref));
|
|
230
214
|
const allFiles = [
|
|
231
215
|
...downloaded,
|
|
232
|
-
...backgroundFiles.map(({
|
|
233
|
-
...
|
|
234
|
-
name: attributedFileName(
|
|
216
|
+
...backgroundFiles.loaded.map(({ value, ref }) => ({
|
|
217
|
+
...value,
|
|
218
|
+
name: attributedFileName(value.name, ref.from, ref.messageId),
|
|
235
219
|
})),
|
|
236
220
|
];
|
|
237
|
-
const allImages = [...imageRefs, ...backgroundImages.map(({
|
|
221
|
+
const allImages = [...imageRefs, ...backgroundImages.loaded.map(({ value }) => value)];
|
|
238
222
|
return {
|
|
239
223
|
images: allImages.length ? allImages : undefined,
|
|
240
224
|
promptSuffix: `${referentBlock}${missingNote}${backgroundImageManifest}${attachedFilesManifest(allFiles)}`,
|
|
@@ -242,25 +226,23 @@ async function resolveTurnInputs(t, attachments) {
|
|
|
242
226
|
};
|
|
243
227
|
}
|
|
244
228
|
/**
|
|
245
|
-
* Run one turn: resolve its inputs, then
|
|
246
|
-
*
|
|
247
|
-
* primary-input failure surfaces as a `failed` event (never a silent drop).
|
|
229
|
+
* Run one turn: resolve its inputs, then ask the agent (invoke-turn-kit — a primary-input failure
|
|
230
|
+
* surfaces as a `failed` event, never a silent drop).
|
|
248
231
|
*/
|
|
249
|
-
export
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
yield* streamTurnWithBusyRetry(agent, scope, prompt, { label: transport.label, onCompleted, busyRetry });
|
|
232
|
+
export function feishuTurnStream(agent, session, text, transport, attachments, busyRetry = DEFAULT_BUSY_RETRY) {
|
|
233
|
+
return turnStream({
|
|
234
|
+
agent,
|
|
235
|
+
label: transport.label,
|
|
236
|
+
busyRetry,
|
|
237
|
+
resolve: () => resolveTurnInputs(transport, attachments),
|
|
238
|
+
turn: (resolved) => ({
|
|
239
|
+
// Lineage is resolved per turn; the engine reads it only when creating a new session.
|
|
240
|
+
scope: (transport.parentSession === undefined
|
|
241
|
+
? { session }
|
|
242
|
+
: { session, parentSession: transport.parentSession, branchHints: resolved.referentIds }),
|
|
243
|
+
prompt: { text: `${text}${resolved.promptSuffix}${REPLY_INSTRUCTION}`, images: resolved.images },
|
|
244
|
+
}),
|
|
245
|
+
// A resource fetch that failed may simply succeed on the redelivery.
|
|
246
|
+
retryableLoadFailure: () => true,
|
|
247
|
+
});
|
|
266
248
|
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Raw wire types stay at the webhook/policy boundary: authors' existing `route(event)` callbacks keep
|
|
5
|
-
* receiving the platform event unchanged. The narrow normalized shape below owns only what currently
|
|
6
|
-
* benefits from normalization: conversation-place identity, decoded content, mention presence, and
|
|
7
|
-
* message-scoped resource locators. Do not pre-model unused transport metadata for a future ingress.
|
|
8
|
-
*/
|
|
9
|
-
/** The v2 event envelope header. Feishu and Lark use the same wire shape. */
|
|
1
|
+
/** Canonical Feishu/Lark protocol and normalized-message models. */
|
|
2
|
+
/** The v2 event envelope header. */
|
|
10
3
|
export interface FeishuEventHeader {
|
|
11
4
|
event_id?: string;
|
|
12
5
|
event_type?: string;
|
|
@@ -16,7 +9,7 @@ export interface FeishuEventHeader {
|
|
|
16
9
|
tenant_key?: string;
|
|
17
10
|
[k: string]: unknown;
|
|
18
11
|
}
|
|
19
|
-
/** One entry of a message's `mentions` array.
|
|
12
|
+
/** One entry of a message's `mentions` array. */
|
|
20
13
|
export interface FeishuMention {
|
|
21
14
|
key: string;
|
|
22
15
|
id?: {
|
|
@@ -25,11 +18,10 @@ export interface FeishuMention {
|
|
|
25
18
|
union_id?: string;
|
|
26
19
|
};
|
|
27
20
|
name?: string;
|
|
28
|
-
mentioned_type?: string;
|
|
29
21
|
tenant_key?: string;
|
|
30
22
|
[k: string]: unknown;
|
|
31
23
|
}
|
|
32
|
-
/** A received `im.message.receive_v1` message.
|
|
24
|
+
/** A received `im.message.receive_v1` message. */
|
|
33
25
|
export interface FeishuMessage {
|
|
34
26
|
message_id: string;
|
|
35
27
|
root_id?: string;
|
|
@@ -42,11 +34,6 @@ export interface FeishuMessage {
|
|
|
42
34
|
message_type: string;
|
|
43
35
|
content: string;
|
|
44
36
|
mentions?: FeishuMention[];
|
|
45
|
-
user_agent?: string;
|
|
46
|
-
lark_agent_context?: {
|
|
47
|
-
active_chat_id?: string;
|
|
48
|
-
[k: string]: unknown;
|
|
49
|
-
};
|
|
50
37
|
[k: string]: unknown;
|
|
51
38
|
}
|
|
52
39
|
export interface FeishuSender {
|
|
@@ -72,10 +59,6 @@ export interface FeishuRoute {
|
|
|
72
59
|
text?: string;
|
|
73
60
|
}
|
|
74
61
|
export type FeishuResourceKind = "image" | "file" | "audio" | "video";
|
|
75
|
-
/**
|
|
76
|
-
* A resource locator. User-sent resources are scoped by BOTH their carrying message id and resource
|
|
77
|
-
* key; a bare file_key/image_key is insufficient for the message-resource download API.
|
|
78
|
-
*/
|
|
79
62
|
interface FeishuResourceRef {
|
|
80
63
|
kind: FeishuResourceKind;
|
|
81
64
|
messageId: string;
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical Feishu/Lark protocol and normalized-message models.
|
|
3
|
-
*
|
|
4
|
-
* Raw wire types stay at the webhook/policy boundary: authors' existing `route(event)` callbacks keep
|
|
5
|
-
* receiving the platform event unchanged. The narrow normalized shape below owns only what currently
|
|
6
|
-
* benefits from normalization: conversation-place identity, decoded content, mention presence, and
|
|
7
|
-
* message-scoped resource locators. Do not pre-model unused transport metadata for a future ingress.
|
|
8
|
-
*/
|
|
1
|
+
/** Canonical Feishu/Lark protocol and normalized-message models. */
|
|
9
2
|
export {};
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure Feishu/Lark message normalization. The platform sends a stable event shell but encodes the
|
|
3
|
-
* actual message body as a JSON string selected by `message_type`; this module is the one decoder and
|
|
4
|
-
* converts resource keys into message-scoped locators before the turn engine sees them.
|
|
5
|
-
*/
|
|
1
|
+
/** Pure Feishu/Lark message normalization. */
|
|
6
2
|
import type { FeishuMessage, FeishuMessageEvent, FeishuResourceKind, NormalizedFeishuMessage } from "./model.ts";
|
|
7
3
|
interface DecodedFeishuResource {
|
|
8
4
|
kind: FeishuResourceKind;
|
|
@@ -13,11 +9,7 @@ export interface DecodedFeishuContent {
|
|
|
13
9
|
text: string;
|
|
14
10
|
resources: DecodedFeishuResource[];
|
|
15
11
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Decode one JSON-string message body. Unknown or malformed external input degrades to a visible
|
|
18
|
-
* marker rather than throwing, preserving the channel's existing fail-visible prompt behavior.
|
|
19
|
-
*/
|
|
12
|
+
/** Decode one JSON-string message body. */
|
|
20
13
|
export declare function decodeFeishuContent(message: Pick<FeishuMessage, "message_type" | "content" | "mentions">): DecodedFeishuContent;
|
|
21
|
-
/** Normalize one verified message event. Returns null only when its required identity is absent. */
|
|
22
14
|
export declare function normalizeFeishuMessage(event: FeishuMessageEvent): NormalizedFeishuMessage | null;
|
|
23
15
|
export {};
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Render one paragraph of tagged nodes to a line, collecting any resource it carries INTO the sink
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Shared by `post` and `interactive` because the platform hands both out in the same shape. Card-only
|
|
6
|
-
* shapes are handled here rather than in a second walker: `note` nests its own `elements`, and the
|
|
7
|
-
* widget tags (button/select/overflow/date_picker) carry their user-visible label in `text` or
|
|
8
|
-
* `placeholder` — a card is read for what it SAYS, so a label is content and an unlabelled control is
|
|
9
|
-
* nothing.
|
|
10
|
-
*
|
|
11
|
-
* The OPTIONAL sink is the whole reason this is a parameter rather than a return value: a card's
|
|
12
|
-
* resources are documented as unfetchable (see the card branch), so that caller renders the same
|
|
13
|
-
* `[image]` / `[video]` markers into the text while collecting nothing. The markers still tell the
|
|
14
|
-
* model what is there; what must not happen is a key entering the turn's PRIMARY inputs, which load
|
|
15
|
-
* fail-fast.
|
|
2
|
+
* Render one paragraph of tagged nodes to a line, collecting any resource it carries INTO the sink the caller supplies
|
|
3
|
+
* — or none, when the caller passes no sink.
|
|
16
4
|
*/
|
|
17
5
|
function renderNodes(nodes, resources) {
|
|
18
6
|
if (!Array.isArray(nodes))
|
|
@@ -70,10 +58,7 @@ function restoreMentions(text, mentions) {
|
|
|
70
58
|
}
|
|
71
59
|
return out;
|
|
72
60
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Decode one JSON-string message body. Unknown or malformed external input degrades to a visible
|
|
75
|
-
* marker rather than throwing, preserving the channel's existing fail-visible prompt behavior.
|
|
76
|
-
*/
|
|
61
|
+
/** Decode one JSON-string message body. */
|
|
77
62
|
export function decodeFeishuContent(message) {
|
|
78
63
|
const rawType = typeof message.message_type === "string" ? message.message_type : "unknown";
|
|
79
64
|
let content;
|
|
@@ -102,18 +87,7 @@ export function decodeFeishuContent(message) {
|
|
|
102
87
|
}
|
|
103
88
|
return { text: lines.join("\n"), resources };
|
|
104
89
|
}
|
|
105
|
-
// A CARD, as the platform hands it BACK.
|
|
106
|
-
// (`{type:"card",data:{card_id}}`, card.ts) whose text lives in cardkit — but a query API renders
|
|
107
|
-
// the card down to `title` + `elements` (paragraphs of the same tagged nodes as `post`), so the
|
|
108
|
-
// content is readable without a second remote call. This is the message type the agent's OWN
|
|
109
|
-
// answers are, so the case that matters is a user following up on one: without this branch a
|
|
110
|
-
// reply-referent that is the agent's own card decoded to the bare `[interactive message]` marker
|
|
111
|
-
// and the model was told its own answer was unreadable (field-observed).
|
|
112
|
-
//
|
|
113
|
-
// BOTH spellings on purpose: the platform's own docs disagree with themselves — the field table
|
|
114
|
-
// says `interactive` (what the receive EVENT carries) while the message-object example shows
|
|
115
|
-
// `"msg_type": "card"`. Matching one would leave the other silently on the default branch, which
|
|
116
|
-
// is exactly the symptom this fixes.
|
|
90
|
+
// A CARD, as the platform hands it BACK.
|
|
117
91
|
case "interactive":
|
|
118
92
|
case "card": {
|
|
119
93
|
const lines = [];
|
|
@@ -122,21 +96,13 @@ export function decodeFeishuContent(message) {
|
|
|
122
96
|
lines.push(title);
|
|
123
97
|
const paragraphs = Array.isArray(content.elements) ? content.elements : [];
|
|
124
98
|
for (const paragraph of paragraphs) {
|
|
125
|
-
// NO resource sink, deliberately.
|
|
126
|
-
// fetched at all: `im/v1/messages/:id/resources/:key` answers 234043 ("Unsupported message
|
|
127
|
-
// type") for a card message id, by stated limitation rather than by permission. Collecting a
|
|
128
|
-
// key here would hand the turn a PRIMARY input that is guaranteed to fail its fail-fast load
|
|
129
|
-
// — turning "the card reads as a marker" (the old behaviour) into "the whole turn errors",
|
|
130
|
-
// which is strictly worse than the gap this branch exists to close. The text still renders
|
|
131
|
-
// `[image]` / `[video]`, so the model knows what is there and that it does not have it.
|
|
132
|
-
//
|
|
133
|
-
// Tolerate both shapes: elements as paragraphs (array of arrays) and a flat element list.
|
|
99
|
+
// NO resource sink, deliberately.
|
|
134
100
|
const line = Array.isArray(paragraph) ? renderNodes(paragraph) : renderNodes([paragraph]);
|
|
135
101
|
if (line)
|
|
136
102
|
lines.push(line);
|
|
137
103
|
}
|
|
138
|
-
// An unrenderable card (all controls, no labels) still says something by existing — keep the
|
|
139
|
-
//
|
|
104
|
+
// An unrenderable card (all controls, no labels) still says something by existing — keep the marker rather than
|
|
105
|
+
// returning empty, which reads as "the message was blank".
|
|
140
106
|
return { text: lines.length > 0 ? lines.join("\n") : `[${rawType} message]`, resources };
|
|
141
107
|
}
|
|
142
108
|
case "image": {
|
|
@@ -176,7 +142,6 @@ export function decodeFeishuContent(message) {
|
|
|
176
142
|
return { text: `[${rawType} message]`, resources };
|
|
177
143
|
}
|
|
178
144
|
}
|
|
179
|
-
/** Normalize one verified message event. Returns null only when its required identity is absent. */
|
|
180
145
|
export function normalizeFeishuMessage(event) {
|
|
181
146
|
const message = event.message;
|
|
182
147
|
if (!message || typeof message.message_id !== "string" || typeof message.chat_id !== "string")
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical Feishu protocol policy and prompt-envelope helpers — PURE. Raw event types remain public
|
|
3
|
-
* for the existing `route(event)` authoring surface; JSON-string content decoding is delegated to the
|
|
4
|
-
* normalized-message boundary in normalize.ts so the turn engine and compatibility wrappers share one
|
|
5
|
-
* decoder.
|
|
6
|
-
*/
|
|
1
|
+
/** Canonical Feishu protocol policy and prompt-envelope helpers — PURE. */
|
|
7
2
|
import type { FeishuCloudKind } from "./cloud.ts";
|
|
8
3
|
import type { FeishuMention, FeishuMessage, FeishuMessageEvent, FeishuRoute, FeishuSender } from "./model.ts";
|
|
9
4
|
export type { FeishuMention, FeishuMessage, FeishuMessageEvent, FeishuRoute, FeishuSender };
|
|
10
|
-
/** A resource reduced to what a caller needs to fetch and name it
|
|
11
|
-
* that {@link decodeFeishuContent} attaches are supplied by the caller's own context. */
|
|
5
|
+
/** A resource reduced to what a caller needs to fetch and name it. */
|
|
12
6
|
interface FeishuAttachmentRef {
|
|
13
7
|
key: string;
|
|
14
8
|
name?: string;
|
|
@@ -19,27 +13,15 @@ export interface ParsedFeishuContent {
|
|
|
19
13
|
fileRefs: FeishuAttachmentRef[];
|
|
20
14
|
}
|
|
21
15
|
/**
|
|
22
|
-
* The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own
|
|
23
|
-
*
|
|
24
|
-
* `decodeFeishuContent` stays canonical: this only reshapes what it returns.
|
|
16
|
+
* The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own (the prompt
|
|
17
|
+
* envelope, and the quoted parent whose resources are carried by the PARENT message id).
|
|
25
18
|
*/
|
|
26
19
|
export declare function parseContent(message: Pick<FeishuMessage, "message_type" | "content" | "mentions">): ParsedFeishuContent;
|
|
27
|
-
/** A stable sender label for attribution.
|
|
20
|
+
/** A stable sender label for attribution. */
|
|
28
21
|
export declare function senderLabel(sender: FeishuSender | undefined): string | undefined;
|
|
29
|
-
/** Whichever id flavour the tenant populates.
|
|
30
|
-
* app configuration, not an invariant — callers only ever compare these for distinctness. */
|
|
22
|
+
/** Whichever id flavour the tenant populates. */
|
|
31
23
|
export declare function senderId(sender: FeishuSender | undefined): string | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* The place a message lives (the chat, or a thread within it) — the session key (participant model §5),
|
|
34
|
-
* and the key thread participation is recorded under, since that record is a claim about this session.
|
|
35
|
-
*
|
|
36
|
-
* Branded with the channel kind, like Slack's twin, because session ids share ONE namespace across
|
|
37
|
-
* every channel in a deployment: without it a `feishu` and a `lark` chat carrying the same platform id
|
|
38
|
-
* would answer into the same memory. The length bound is the FILENAME the id becomes (session-store.ts
|
|
39
|
-
* `piSessionId` escapes every character outside `[A-Za-z0-9.-]` as `_XX` / `_uXXXX`, so each `:` costs
|
|
40
|
-
* three), and the worst case here — brand + a 35-char chat id + a 36-char thread id — encodes to well
|
|
41
|
-
* under 100 bytes against the filesystem's 255.
|
|
42
|
-
*/
|
|
24
|
+
/** The place a message lives (the chat, or a thread within it). */
|
|
43
25
|
export declare function placeKey(kind: string, message: Pick<FeishuMessage, "chat_id" | "thread_id">): string;
|
|
44
26
|
/** The canonical Feishu-branded prompt envelope. */
|
|
45
27
|
export declare function feishuEnvelope(event: FeishuMessageEvent): string;
|
|
@@ -48,10 +30,8 @@ export declare function cloudEnvelope(event: FeishuMessageEvent, tag: FeishuClou
|
|
|
48
30
|
/** Whether the parsed mention list contains this bot's app-scoped open_id. */
|
|
49
31
|
export declare function mentionsBot(message: Pick<FeishuMessage, "mentions">, botOpenId: string | undefined): boolean;
|
|
50
32
|
/**
|
|
51
|
-
* Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only
|
|
52
|
-
*
|
|
53
|
-
* stateful channel wiring may additionally admit unmentioned messages in a thread it takes part in
|
|
54
|
-
* (docs/design/participant-model.md §3).
|
|
33
|
+
* Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only when THIS bot is
|
|
34
|
+
* structurally mentioned.
|
|
55
35
|
*/
|
|
56
36
|
export declare function defaultFeishuRoute(event: FeishuMessageEvent, options?: {
|
|
57
37
|
botOpenId?: string;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { decodeFeishuContent } from "./normalize.js";
|
|
2
2
|
/**
|
|
3
|
-
* The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own
|
|
4
|
-
*
|
|
5
|
-
* `decodeFeishuContent` stays canonical: this only reshapes what it returns.
|
|
3
|
+
* The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own (the prompt
|
|
4
|
+
* envelope, and the quoted parent whose resources are carried by the PARENT message id).
|
|
6
5
|
*/
|
|
7
6
|
export function parseContent(message) {
|
|
8
7
|
const decoded = decodeFeishuContent(message);
|
|
@@ -14,27 +13,16 @@ export function parseContent(message) {
|
|
|
14
13
|
.map((resource) => ({ key: resource.key, name: resource.name })),
|
|
15
14
|
};
|
|
16
15
|
}
|
|
17
|
-
/** A stable sender label for attribution.
|
|
16
|
+
/** A stable sender label for attribution. */
|
|
18
17
|
export function senderLabel(sender) {
|
|
19
18
|
const id = senderId(sender);
|
|
20
19
|
return id ? `user ${id}` : undefined;
|
|
21
20
|
}
|
|
22
|
-
/** Whichever id flavour the tenant populates.
|
|
23
|
-
* app configuration, not an invariant — callers only ever compare these for distinctness. */
|
|
21
|
+
/** Whichever id flavour the tenant populates. */
|
|
24
22
|
export function senderId(sender) {
|
|
25
23
|
return sender?.sender_id?.open_id ?? sender?.sender_id?.user_id ?? sender?.sender_id?.union_id;
|
|
26
24
|
}
|
|
27
|
-
/**
|
|
28
|
-
* The place a message lives (the chat, or a thread within it) — the session key (participant model §5),
|
|
29
|
-
* and the key thread participation is recorded under, since that record is a claim about this session.
|
|
30
|
-
*
|
|
31
|
-
* Branded with the channel kind, like Slack's twin, because session ids share ONE namespace across
|
|
32
|
-
* every channel in a deployment: without it a `feishu` and a `lark` chat carrying the same platform id
|
|
33
|
-
* would answer into the same memory. The length bound is the FILENAME the id becomes (session-store.ts
|
|
34
|
-
* `piSessionId` escapes every character outside `[A-Za-z0-9.-]` as `_XX` / `_uXXXX`, so each `:` costs
|
|
35
|
-
* three), and the worst case here — brand + a 35-char chat id + a 36-char thread id — encodes to well
|
|
36
|
-
* under 100 bytes against the filesystem's 255.
|
|
37
|
-
*/
|
|
25
|
+
/** The place a message lives (the chat, or a thread within it). */
|
|
38
26
|
export function placeKey(kind, message) {
|
|
39
27
|
const chat = `${kind}:${message.chat_id}`;
|
|
40
28
|
return message.thread_id ? `${chat}:${message.thread_id}` : chat;
|
|
@@ -53,11 +41,7 @@ export function cloudEnvelope(event, tag) {
|
|
|
53
41
|
`chat ${message.chat_id} (${message.chat_type})`,
|
|
54
42
|
message.thread_id ? `topic ${message.thread_id}` : undefined,
|
|
55
43
|
from ? `from ${from}` : undefined,
|
|
56
|
-
// The message's own id is LOAD-BEARING, not decoration
|
|
57
|
-
// enters the session transcript, and session inheritance locates a thread's branch point by
|
|
58
|
-
// searching the parent transcript for exactly these ids (scope.branchHints — session-inheritance.ts).
|
|
59
|
-
// Remove it and every thread quietly inherits from the room's present instead of the branch
|
|
60
|
-
// point. It also lets the model name what it is answering in a busy chat.
|
|
44
|
+
// The message's own id is LOAD-BEARING, not decoration.
|
|
61
45
|
`msg ${message.message_id}`,
|
|
62
46
|
]
|
|
63
47
|
.filter(Boolean)
|
|
@@ -73,10 +57,8 @@ export function mentionsBot(message, botOpenId) {
|
|
|
73
57
|
return (message.mentions ?? []).some((mention) => mention.id?.open_id === botOpenId);
|
|
74
58
|
}
|
|
75
59
|
/**
|
|
76
|
-
* Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only
|
|
77
|
-
*
|
|
78
|
-
* stateful channel wiring may additionally admit unmentioned messages in a thread it takes part in
|
|
79
|
-
* (docs/design/participant-model.md §3).
|
|
60
|
+
* Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only when THIS bot is
|
|
61
|
+
* structurally mentioned.
|
|
80
62
|
*/
|
|
81
63
|
export function defaultFeishuRoute(event, options) {
|
|
82
64
|
const message = event.message;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { AgentEvent } from "../../agent.ts";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import type * as Stream from "effect/Stream";
|
|
4
|
+
import { type PortFailure } from "../../effect-port.ts";
|
|
2
5
|
import { type FeishuApi, type FeishuTarget } from "./feishu-api.ts";
|
|
3
6
|
import { type ChannelFailure, defaultErrorMessage } from "../kit/preview-kit.ts";
|
|
4
7
|
/** A terminal failure, as the channel hands it to `onError` — the shared channel shape. */
|
|
5
8
|
export type FeishuFailure = ChannelFailure;
|
|
6
9
|
export { defaultErrorMessage };
|
|
7
|
-
/** A visible preview mounted into the chat.
|
|
8
|
-
* one before execution, then hands the exact entity/message to {@link streamFeishuReply} for takeover. */
|
|
10
|
+
/** A visible preview mounted into the chat. */
|
|
9
11
|
export type MountedFeishuPreview = {
|
|
10
12
|
kind: "card";
|
|
11
13
|
cardId: string;
|
|
@@ -15,20 +17,16 @@ export type MountedFeishuPreview = {
|
|
|
15
17
|
messageId: string;
|
|
16
18
|
};
|
|
17
19
|
/**
|
|
18
|
-
* Mount one preview message: preferably a streaming card entity (`initial` seeds the process element;
|
|
19
|
-
*
|
|
20
|
-
* and ordinary turn startup share this constructor so a queued card has exactly the same shape the
|
|
21
|
-
* stream pump expects to take over later.
|
|
20
|
+
* Mount one preview message: preferably a streaming card entity (`initial` seeds the process element; the answer
|
|
21
|
+
* element starts empty), with a static text message as the visible fallback.
|
|
22
22
|
*/
|
|
23
23
|
export declare function mountFeishuPreview(api: FeishuApi, target: FeishuTarget, initial: string, label?: string): Promise<MountedFeishuPreview>;
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
24
|
+
/**
|
|
25
|
+
* Settle a preview without starting an Agent stream: a queue/poison/defer notice, or a recovered answer whose own
|
|
26
|
+
* preview died with the run that produced it (`undefined` — then it is one fresh message).
|
|
27
|
+
*/
|
|
26
28
|
export declare function settleFeishuPreview(api: FeishuApi, target: FeishuTarget, preview: MountedFeishuPreview | undefined, text: string): Promise<void>;
|
|
27
29
|
/**
|
|
28
|
-
* Consume one turn's event stream into a Feishu-compatible chat, live
|
|
29
|
-
* model). Preview updates are best-effort (logged once if they fail); the final write is authoritative
|
|
30
|
-
* and surfaces a real failure (bad credentials, etc.). `initialPreview`, when present, is the queued
|
|
31
|
-
* turn's already-mounted card/text message: the pump and terminal write mutate that same message rather
|
|
32
|
-
* than recalling it and posting another reply.
|
|
30
|
+
* Consume one turn's event stream into a Feishu-compatible chat, live.
|
|
33
31
|
*/
|
|
34
|
-
export declare function
|
|
32
|
+
export declare function feishuReply(events: Stream.Stream<AgentEvent, PortFailure>, api: FeishuApi, target: FeishuTarget, formatError: (failed: FeishuFailure) => string | undefined, initialPreview?: MountedFeishuPreview, label?: string, onAnswered?: (answer: string) => void): Effect.Effect<void, PortFailure, import("effect/Scope").Scope>;
|