@fastagent-sh/fastagent 0.21.0 → 0.22.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 +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 -43
- 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 +209 -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 +153 -228
- 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,4 @@
|
|
|
1
|
-
/** Lightweight Slack emoji ack on the user's triggering message: 👀 while working, ✅ when done.
|
|
2
|
-
* Every failure is non-fatal — the turn's threaded reply is the real deliverable. */
|
|
1
|
+
/** Lightweight Slack emoji ack on the user's triggering message: 👀 while working, ✅ when done. */
|
|
3
2
|
import { log } from "../../log.js";
|
|
4
3
|
const EMOJI_RE = /^(?:[a-z0-9_+-]+)(?:::skin-tone-[2-6])?$/;
|
|
5
4
|
/** Normalize a Slack emoji name (strip surrounding colons, lowercase); return null if invalid. */
|
|
@@ -27,6 +26,22 @@ export function resolveReactionEmojis(reactionAck) {
|
|
|
27
26
|
completed: pick(reactionAck.completed, "white_check_mark", "completed"),
|
|
28
27
|
};
|
|
29
28
|
}
|
|
29
|
+
// Every step is best effort: an ack is decoration, and must never fail the turn carrying it.
|
|
30
|
+
const dropProcessing = ({ api, channelId, ts, emojis, label }) => api
|
|
31
|
+
.removeReaction(channelId, ts, emojis.processing)
|
|
32
|
+
.catch((error) => log.warn(`${label} could not remove the processing reaction: ${String(error)}`));
|
|
33
|
+
const addCompleted = ({ api, channelId, ts, emojis, label }) => api
|
|
34
|
+
.addReaction(channelId, ts, emojis.completed)
|
|
35
|
+
.catch((error) => log.warn(`${label} could not add the completed reaction: ${String(error)}`));
|
|
36
|
+
/**
|
|
37
|
+
* Finish an ack this process did not start: 👀 on the asker's message was added by the run that produced the answer,
|
|
38
|
+
* and a re-delivery is the only thing left that can turn it into ✅. Without it the ack says "still working" under a
|
|
39
|
+
* delivered answer, forever.
|
|
40
|
+
*/
|
|
41
|
+
export async function completeSlackReaction(target) {
|
|
42
|
+
await dropProcessing(target);
|
|
43
|
+
await addCompleted(target);
|
|
44
|
+
}
|
|
30
45
|
const NO_REACTION = {
|
|
31
46
|
complete: async () => undefined,
|
|
32
47
|
remove: async () => undefined,
|
|
@@ -46,16 +61,12 @@ export async function startSlackReaction(args) {
|
|
|
46
61
|
if (!active)
|
|
47
62
|
return;
|
|
48
63
|
active = false;
|
|
49
|
-
await
|
|
50
|
-
.removeReaction(channelId, ts, emojis.processing)
|
|
51
|
-
.catch((error) => log.warn(`${label} could not remove the processing reaction: ${String(error)}`));
|
|
64
|
+
await dropProcessing(args);
|
|
52
65
|
};
|
|
53
66
|
return {
|
|
54
67
|
complete: async () => {
|
|
55
68
|
await removeProcessing();
|
|
56
|
-
await
|
|
57
|
-
.addReaction(channelId, ts, emojis.completed)
|
|
58
|
-
.catch((error) => log.warn(`${label} could not add the completed reaction: ${String(error)}`));
|
|
69
|
+
await addCompleted(args);
|
|
59
70
|
},
|
|
60
71
|
remove: removeProcessing,
|
|
61
72
|
};
|
|
@@ -23,8 +23,7 @@ export async function registerSlackWebhook(baseUrl, options) {
|
|
|
23
23
|
const consoleFallback = `set ${publicBaseUrl}/slack as the Event Subscriptions Request URL in the Slack console`;
|
|
24
24
|
let current;
|
|
25
25
|
try {
|
|
26
|
-
// Rotation is not retried with the manifest below
|
|
27
|
-
// repeat would spend tokens on a failure that is about the URL, not about the credential.
|
|
26
|
+
// Rotation is not retried with the manifest below.
|
|
28
27
|
current = await currentSlackConfigToken(options.stateRoot, state, {
|
|
29
28
|
apiBaseUrl: options.apiBaseUrl,
|
|
30
29
|
fetch: options.fetch,
|
|
@@ -35,16 +34,14 @@ export async function registerSlackWebhook(baseUrl, options) {
|
|
|
35
34
|
`re-run \`fastagent add slack --replace-config\` to repair it, or ${consoleFallback}`);
|
|
36
35
|
return "failed";
|
|
37
36
|
}
|
|
38
|
-
// Slack verifies the new request_url with a challenge DURING apps.manifest.update, from Slack's own
|
|
39
|
-
// network — that verdict IS the readiness signal, so it is retried while a fresh tunnel/container
|
|
40
|
-
// warms up. No local `/health` poll precedes it: this machine's reach is the wrong question (#421).
|
|
37
|
+
// Slack verifies the new request_url with a challenge DURING apps.manifest.update, from Slack's own network.
|
|
41
38
|
try {
|
|
42
39
|
await retryWhile(() => updateSlackAppManifest(current.token, current.state.appId, buildSlackManifest({
|
|
43
40
|
name: current.state.appName,
|
|
44
41
|
groupBehavior: current.state.groupBehavior,
|
|
45
42
|
requestUrl: `${publicBaseUrl}/slack`,
|
|
46
|
-
// A manifest update replaces the whole manifest and redirect_urls may not be empty, so a
|
|
47
|
-
//
|
|
43
|
+
// A manifest update replaces the whole manifest and redirect_urls may not be empty, so a placeholder is
|
|
44
|
+
// declared.
|
|
48
45
|
redirectUrl: `${publicBaseUrl}/slack/oauth/callback`,
|
|
49
46
|
}), { apiBaseUrl: options.apiBaseUrl, fetch: options.fetch }), isSlackRequestUrlUnverified, {
|
|
50
47
|
attempts: options.attempts,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { slackChannel } from "@fastagent-sh/fastagent/slack";
|
|
2
|
+
import { defineChannel } from "@fastagent-sh/fastagent";
|
|
2
3
|
|
|
3
4
|
// Slack HTTP Events API channel. Setup:
|
|
4
5
|
// 1. Create a Slack app at https://api.slack.com/apps and add a bot user.
|
|
@@ -10,17 +11,23 @@ import { slackChannel } from "@fastagent-sh/fastagent/slack";
|
|
|
10
11
|
// Set Request URL to https://<host>/slack.
|
|
11
12
|
// 4. Install the app (reinstall after changing scopes) and leave token rotation OFF: it cannot be
|
|
12
13
|
// turned off again, and this channel takes one long-lived Bot User OAuth Token.
|
|
13
|
-
export default
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
export default defineChannel({
|
|
15
|
+
// The env vars this channel needs. fastagent carries them to a deployed box and refuses to serve
|
|
16
|
+
// while one is unset — a bare process.env read gets neither guarantee.
|
|
17
|
+
secrets: ["SLACK_BOT_TOKEN", "SLACK_SIGNING_SECRET"],
|
|
18
|
+
channel: (secrets) =>
|
|
19
|
+
slackChannel({
|
|
20
|
+
botToken: secrets.SLACK_BOT_TOKEN, // OAuth & Permissions → Bot User OAuth Token (xoxb-…)
|
|
21
|
+
signingSecret: secrets.SLACK_SIGNING_SECRET, // Basic Information → App Credentials
|
|
22
|
+
// Slack Agent stream; its inline tool traces show each call's first argument and stay in the
|
|
23
|
+
// delivered message. "classic" settles into the answer alone (and gives up native streaming).
|
|
24
|
+
rendering: "native",
|
|
25
|
+
// Optional per-reply footer, if your policy requires one: aiDisclaimer: "AI-generated; verify important information.",
|
|
26
|
+
// welcome: "Custom first-run DM greeting", // sent once on first DM open; false disables (default: a generic greeting)
|
|
27
|
+
// reactionAck: false, // disable the 👀→✅ ack on the user's message (default on; needs reactions:write)
|
|
28
|
+
// No session modes: an answer attaches to its question with a thread (Slack has no quote primitive),
|
|
29
|
+
// and that thread is the session — see docs/design/participant-model.md.
|
|
30
|
+
// Dev/personal bot: surface raw errors. Remove this for a customer-facing bot; details remain in logs.
|
|
31
|
+
onError: (failed) => `⚠️ ${failed.details}`,
|
|
32
|
+
}),
|
|
26
33
|
});
|
|
@@ -3,13 +3,13 @@ import { slackTransport } from "@fastagent-sh/fastagent/slack";
|
|
|
3
3
|
|
|
4
4
|
// Send a message or upload a local file to Slack. In a CHAT turn the channel delivers the reply
|
|
5
5
|
// itself — do NOT call this to answer a normal chat turn (that posts the message twice). This tool is
|
|
6
|
-
// for file uploads, and for turns NO channel is carrying: a scheduled turn (
|
|
6
|
+
// for file uploads, and for turns NO channel is carrying: a scheduled turn (routines/<name>.ts) or a
|
|
7
7
|
// self-scheduled wake-up, whose plain reply is not delivered anywhere. The channelId/threadTs come
|
|
8
8
|
// from the [slack: …] context line in a chat turn; a scheduled/woken turn has no such line, so its
|
|
9
9
|
// prompt must name the target channel id. tools/ is auto-discovered.
|
|
10
10
|
//
|
|
11
11
|
// Delivery rides the channel's own transport (slackTransport): its token, API base, Markdown splitting
|
|
12
|
-
// and rate-limit handling. With no channel mounted (`fastagent
|
|
12
|
+
// and rate-limit handling. With no channel mounted (`fastagent routine run` / `invoke`) it is built from
|
|
13
13
|
// SLACK_BOT_TOKEN in .env.
|
|
14
14
|
|
|
15
15
|
export default defineTool({
|
|
@@ -9,9 +9,5 @@ export interface SlackSetupServer {
|
|
|
9
9
|
}>;
|
|
10
10
|
close(): Promise<void>;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Temporary onboarding-only responder. Its unguessable paths live for one command: one path echoes only
|
|
14
|
-
* Slack's URL-verification challenge, while the other captures one OAuth redirect. It never accepts
|
|
15
|
-
* event callbacks or runs Agent work.
|
|
16
|
-
*/
|
|
12
|
+
/** Temporary onboarding-only responder. */
|
|
17
13
|
export declare function startSlackSetupServer(): Promise<SlackSetupServer>;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { createServer } from "node:http";
|
|
3
|
-
/**
|
|
4
|
-
* Temporary onboarding-only responder. Its unguessable paths live for one command: one path echoes only
|
|
5
|
-
* Slack's URL-verification challenge, while the other captures one OAuth redirect. It never accepts
|
|
6
|
-
* event callbacks or runs Agent work.
|
|
7
|
-
*/
|
|
3
|
+
/** Temporary onboarding-only responder. */
|
|
8
4
|
export async function startSlackSetupServer() {
|
|
9
5
|
const nonce = randomBytes(24).toString("hex");
|
|
10
6
|
const requestPath = `/slack/setup/${nonce}`;
|
|
@@ -3,8 +3,5 @@ import { type SlackApi } from "./slack-api.ts";
|
|
|
3
3
|
export type SlackTransport = Pick<SlackApi, "sendMarkdown" | "uploadFile">;
|
|
4
4
|
/** A re-mount replaces the entry: the channel's transport is the authoritative one for its root. */
|
|
5
5
|
export declare function registerSlackApi(stateRoot: string, api: SlackApi): void;
|
|
6
|
-
/**
|
|
7
|
-
* The transport of the agent whose workspace is `cwd` (a tool's `ctx.cwd`). The state root is derived
|
|
8
|
-
* exactly as the opener derives it for the channel, so both name the same mount.
|
|
9
|
-
*/
|
|
6
|
+
/** The transport of the agent whose workspace is `cwd` (a tool's `ctx.cwd`). */
|
|
10
7
|
export declare function slackTransport(cwd: string): SlackTransport;
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The ONE Slack transport per state root a process holds: the mounted channel's, shared with the
|
|
3
|
-
* scaffolded send tool.
|
|
4
|
-
*
|
|
5
|
-
* The tool used to carry a transport of its own over `SLACK_BOT_TOKEN` (#458). Sharing the channel's
|
|
6
|
-
* gives it the channel's `apiBaseUrl`, Markdown splitting and rate-limit handling, and one place to
|
|
7
|
-
* read the credential. The channel registers at mount; the tool resolves at EXECUTE, never at load,
|
|
8
|
-
* and builds a transport from the env only where no channel is mounted (`fastagent fire` / `invoke`)
|
|
9
|
-
* — that fallback knows no `apiBaseUrl`, since the option lives in the channel's glue, which is not
|
|
10
|
-
* loaded on those paths.
|
|
2
|
+
* The ONE Slack transport per state root a process holds: the mounted channel's, shared with the scaffolded send tool.
|
|
11
3
|
*/
|
|
12
4
|
import { resolvePlacement, resolveStateRoot } from "../../paths.js";
|
|
13
5
|
import { createSlackApi } from "./slack-api.js";
|
|
@@ -16,10 +8,7 @@ const byStateRoot = new Map();
|
|
|
16
8
|
export function registerSlackApi(stateRoot, api) {
|
|
17
9
|
byStateRoot.set(stateRoot, api);
|
|
18
10
|
}
|
|
19
|
-
/**
|
|
20
|
-
* The transport of the agent whose workspace is `cwd` (a tool's `ctx.cwd`). The state root is derived
|
|
21
|
-
* exactly as the opener derives it for the channel, so both name the same mount.
|
|
22
|
-
*/
|
|
11
|
+
/** The transport of the agent whose workspace is `cwd` (a tool's `ctx.cwd`). */
|
|
23
12
|
export function slackTransport(cwd) {
|
|
24
13
|
const stateRoot = resolveStateRoot(resolvePlacement(cwd).agentDir);
|
|
25
14
|
let api = byStateRoot.get(stateRoot);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ImageRef } from "../../agent.ts";
|
|
2
|
+
import type { CallOptions } from "../kit/transport.ts";
|
|
2
3
|
import type { SlackFile } from "./model.ts";
|
|
3
4
|
export interface SlackTarget {
|
|
4
5
|
channelId: string;
|
|
@@ -46,7 +47,7 @@ export interface SlackApi {
|
|
|
46
47
|
postMessage(target: SlackTarget, text: string): Promise<string>;
|
|
47
48
|
postMarkdown(target: SlackTarget, markdown: string): Promise<string>;
|
|
48
49
|
updateMessage(channelId: string, ts: string, text: string): Promise<void>;
|
|
49
|
-
updateMarkdown(channelId: string, ts: string, markdown: string): Promise<void>;
|
|
50
|
+
updateMarkdown(channelId: string, ts: string, markdown: string, opts?: CallOptions): Promise<void>;
|
|
50
51
|
deleteMessage(channelId: string, ts: string): Promise<void>;
|
|
51
52
|
/** Post standard Markdown, split under Slack's limit. `target.channelId` may be a user id: Slack
|
|
52
53
|
* then opens (or reuses) the app's DM with that user, and the result names it. */
|
|
@@ -37,6 +37,7 @@ const NATIVE_UNAVAILABLE_ERRORS = new Set([
|
|
|
37
37
|
export function isSlackNativeUnavailable(error) {
|
|
38
38
|
return error instanceof SlackApiError && !!error.slackError && NATIVE_UNAVAILABLE_ERRORS.has(error.slackError);
|
|
39
39
|
}
|
|
40
|
+
/** Sleep on the GLOBAL timer (not `node:timers/promises`) so tests can drive it with fake timers. */
|
|
40
41
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
42
|
/** Split a Slack text/Markdown field at a code-point-safe boundary, preferring a newline. */
|
|
42
43
|
export function chunkSlackText(text, maxPoints = SLACK_MAX_MARKDOWN) {
|
|
@@ -145,7 +146,8 @@ function assertLongLivedBotToken(botToken) {
|
|
|
145
146
|
export function createSlackApi({ botToken, baseUrl = "https://slack.com/api" }) {
|
|
146
147
|
assertLongLivedBotToken(botToken);
|
|
147
148
|
const apiBase = baseUrl.replace(/\/$/, "");
|
|
148
|
-
const call = async (method, body, httpMethod = "POST") => {
|
|
149
|
+
const call = async (method, body, httpMethod = "POST", opts = {}) => {
|
|
150
|
+
const retries = opts.retries ?? RETRIES;
|
|
149
151
|
const url = new URL(`${apiBase}/${method}`);
|
|
150
152
|
if (httpMethod === "GET") {
|
|
151
153
|
for (const [name, value] of Object.entries(body)) {
|
|
@@ -181,7 +183,7 @@ export function createSlackApi({ botToken, baseUrl = "https://slack.com/api" })
|
|
|
181
183
|
if (response.ok && data.ok === true)
|
|
182
184
|
return data;
|
|
183
185
|
const rateLimited = response.status === 429 || data.error === "ratelimited";
|
|
184
|
-
if (rateLimited && attempt <
|
|
186
|
+
if (rateLimited && attempt < retries) {
|
|
185
187
|
const retryAfter = Number(response.headers.get("retry-after") ?? attempt + 1);
|
|
186
188
|
if (Number.isFinite(retryAfter) && retryAfter <= MAX_RETRY_AFTER_S) {
|
|
187
189
|
await wait(Math.max(1, retryAfter) * 1000);
|
|
@@ -261,9 +263,9 @@ export function createSlackApi({ botToken, baseUrl = "https://slack.com/api" })
|
|
|
261
263
|
throw error;
|
|
262
264
|
}
|
|
263
265
|
},
|
|
264
|
-
async updateMarkdown(channelId, ts, markdown) {
|
|
266
|
+
async updateMarkdown(channelId, ts, markdown, opts) {
|
|
265
267
|
try {
|
|
266
|
-
await call("chat.update", { channel: channelId, ts, markdown_text: markdown });
|
|
268
|
+
await call("chat.update", { channel: channelId, ts, markdown_text: markdown }, "POST", opts);
|
|
267
269
|
}
|
|
268
270
|
catch (error) {
|
|
269
271
|
if (error instanceof SlackApiError && error.slackError === "message_not_modified")
|
|
@@ -8,23 +8,20 @@ export interface SlackChannelOptions {
|
|
|
8
8
|
botToken: string;
|
|
9
9
|
/** App signing secret used to verify the raw Events API request body. */
|
|
10
10
|
signingSecret: string;
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
* naming a thread. */
|
|
11
|
+
/**
|
|
12
|
+
* `native` (default) uses Slack Agent streams for threaded replies; `classic` retains the compatibility renderer
|
|
13
|
+
* based on one rate-limited edited message. A top-level target necessarily uses `classic`, because Slack streams
|
|
14
|
+
* require a parent user message — a custom route reaches one either by returning `threadTs: null` or by redirecting
|
|
15
|
+
* to another channel without naming a thread.
|
|
16
|
+
*/
|
|
18
17
|
rendering?: SlackRendering;
|
|
19
|
-
/** Optional footer for successful Agent replies.
|
|
18
|
+
/** Optional footer for successful Agent replies. */
|
|
20
19
|
aiDisclaimer?: string | false;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
|
|
20
|
+
/**
|
|
21
|
+
* First-run direct-message welcome, sent once when a user first opens the DM (`app_home_opened`, `tab: "messages"`).
|
|
22
|
+
*/
|
|
24
23
|
welcome?: string | false;
|
|
25
|
-
/** Lightweight emoji ack on the user's triggering message: 👀 while working, ✅ when done.
|
|
26
|
-
* disables it; an object overrides either emoji name. Requires the `reactions:write` scope; a missing
|
|
27
|
-
* scope degrades to no ack. */
|
|
24
|
+
/** Lightweight emoji ack on the user's triggering message: 👀 while working, ✅ when done. */
|
|
28
25
|
reactionAck?: false | {
|
|
29
26
|
processing?: string;
|
|
30
27
|
completed?: string;
|