@cursor/july 0.1.104 → 0.1.107
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/bin/agent-serve.js +1 -8
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -0
- package/dist/channels/deployments/types.d.ts +7 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/types.d.ts +2 -4
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/types.d.ts +2 -3
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.DbMWUyGb.js → app.CtuckIiL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DXXZxiMv.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DcNeTh9o.js → VPLocalSearchBox.Bkkhnu8K.js} +2 -2
- package/dist/docs/assets/chunks/{theme.DMjhY3gl.js → theme.DhpIe0Pa.js} +2 -2
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.js +9 -0
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.lean.js +1 -0
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/index.md.BW_6tOgR.js +5 -0
- package/dist/docs/assets/index.md.BW_6tOgR.lean.js +1 -0
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CJNc_xYK.js → reference_cli.md.Dm67hd2D.js} +3 -2
- package/dist/docs/assets/{reference_extensions.md.DykHW3qL.js → reference_extensions.md.CGmMLblt.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.js +3 -0
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.lean.js +1 -0
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +6 -6
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +6 -6
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/grokbot-agents.html +35 -0
- package/dist/docs/guides/grokbot-agents.md +88 -0
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +6 -6
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +8 -8
- package/dist/docs/index.md +6 -1
- package/dist/docs/llms-full.txt +178 -30
- package/dist/docs/llms.txt +2 -0
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +10 -9
- package/dist/docs/reference/cli.md +7 -3
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +6 -6
- package/dist/docs/skills/debug.html +5 -5
- package/dist/docs/skills/evals.html +6 -6
- package/dist/docs/skills/framework-map.html +5 -5
- package/dist/docs/skills/github.html +6 -6
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +29 -0
- package/dist/docs/templates/grokbot-agents.md +48 -0
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/files.d.ts +7 -2
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -2
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +23 -11
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +14 -0
- package/dist/internal/deploy-manifest.d.ts +3 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +15 -12
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-file-storage.d.ts +3 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +3 -1
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +2 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +48 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +60 -0
- package/dist/internal/hosted-delivery.d.ts +17 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +112 -19
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -1
- package/dist/internal/hosted-managed-automation.js +27 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -1
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/reminder-control-plane-protocol.d.ts +187 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +244 -0
- package/dist/internal/reminder-runner.d.ts +48 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +336 -48
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/sdk-runner.d.ts +12 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +18 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +78 -30
- package/dist/internal/session-engine.d.ts +12 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +137 -52
- package/dist/internal/store-mirror.d.ts +2 -2
- package/dist/internal/store-mirror.js +2 -2
- package/dist/internal/tenant-slack/relay.d.ts +2 -0
- package/dist/internal/tenant-slack/relay.d.ts.map +1 -1
- package/dist/internal/tenant-slack/relay.js +18 -8
- package/dist/internal/workspace-sync.d.ts +31 -6
- package/dist/internal/workspace-sync.d.ts.map +1 -1
- package/dist/internal/workspace-sync.js +67 -12
- package/dist/internal/workspace.d.ts +9 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +16 -0
- package/dist/playground/assets/index-Bq2HpEQB.js +67 -0
- package/dist/playground/assets/index-CZKKNlmb.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- package/dist/types.d.ts +98 -28
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +6 -1
- package/docs/guides/grokbot-agents.md +93 -0
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +7 -3
- package/docs/reference/extensions.md +2 -0
- package/docs/templates/grokbot-agents.md +53 -0
- package/package.json +12 -3
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +1 -9
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/deployments-channel.ts +1 -0
- package/src/channels/deployments/types.ts +7 -8
- package/src/channels/github/types.ts +2 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/types.ts +2 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/files.ts +9 -2
- package/src/index.ts +6 -3
- package/src/internal/cli-deploy.ts +30 -12
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +16 -0
- package/src/internal/deploy-manifest.ts +16 -11
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-file-storage.ts +3 -1
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +3 -0
- package/src/internal/hosted-delivery-protocol.ts +96 -0
- package/src/internal/hosted-delivery.ts +207 -28
- package/src/internal/hosted-managed-automation.ts +49 -5
- package/src/internal/init-project.ts +4 -1
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/reminder-control-plane-protocol.ts +499 -0
- package/src/internal/reminder-runner.ts +421 -48
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/sdk-runner.ts +19 -0
- package/src/internal/server.ts +85 -16
- package/src/internal/session-engine.ts +173 -56
- package/src/internal/store-mirror.ts +2 -2
- package/src/internal/tenant-slack/relay.ts +28 -4
- package/src/internal/workspace-sync.ts +84 -12
- package/src/internal/workspace.ts +20 -0
- package/src/reminders.ts +35 -4
- package/src/types.ts +104 -28
- package/templates/grokbot-agents/README.md +26 -0
- package/templates/grokbot-agents/agent/agent.ts +6 -0
- package/templates/grokbot-agents/agent/extensions/grokbot.ts +5 -0
- package/templates/grokbot-agents/agent/instructions.md +7 -0
- package/templates/grokbot-agents/evals/evals.config.ts +5 -0
- package/templates/grokbot-agents/evals/grokbot-agents.eval.ts +18 -0
- package/templates/grokbot-agents/init.json +18 -0
- package/templates/grokbot-agents/package.json +17 -0
- package/templates/grokbot-agents/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.Bqsulb9K.js +0 -1
- package/dist/docs/assets/index.md.D75GWhPl.js +0 -5
- package/dist/docs/assets/index.md.D75GWhPl.lean.js +0 -1
- package/dist/playground/assets/index-8YiozU89.js +0 -67
- package/dist/playground/assets/index-MbMxXg-y.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.CJNc_xYK.lean.js → reference_cli.md.Dm67hd2D.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.DykHW3qL.lean.js → reference_extensions.md.CGmMLblt.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Cursor Grok Bot agents"
|
|
3
|
+
description: "Let an agent-sdk agent talk to your Grok Bot agents: mount the extension, name the bots it may reach, and decide what needs approval."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cursor Grok Bot agents
|
|
7
|
+
|
|
8
|
+
The `cursor-grokbot-agents` extension lets an agent send a message to
|
|
9
|
+
one of your Grok Bot agents and read the reply. The Grok Bot keeps its
|
|
10
|
+
own conversation, memory, and tools. Your agent stays where it is and
|
|
11
|
+
consults that bot the way you would in the Grok Bot app.
|
|
12
|
+
|
|
13
|
+
This is different from moving this agent's turns onto a hosted Grok Bot.
|
|
14
|
+
The extension keeps the agent where it is and lets it talk to *other*
|
|
15
|
+
Grok Bot agents.
|
|
16
|
+
|
|
17
|
+
## Mount it
|
|
18
|
+
|
|
19
|
+
The extension ships with `@cursor/july`. Mount it with one file.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// agent/extensions/grokbot.ts
|
|
23
|
+
import cursorGrokBotAgents from "@cursor/july/extensions/cursor-grokbot-agents";
|
|
24
|
+
|
|
25
|
+
export default cursorGrokBotAgents({
|
|
26
|
+
agents: [
|
|
27
|
+
{ name: "Plan Keeper", description: "Keeps or moves outdoor plans." },
|
|
28
|
+
{ name: "Chief of Staff", description: "Routes work and tracks priorities." },
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`agents` is the allowlist. List every Grok Bot the model may talk to;
|
|
34
|
+
a name outside the list is refused. Calls run under the host's
|
|
35
|
+
signed-in account (`agent-sdk login` or `CURSOR_API_KEY`). Keep
|
|
36
|
+
approval on when you can't.
|
|
37
|
+
|
|
38
|
+
Start from the [Grok Bot agents template](../templates/grokbot-agents.md)
|
|
39
|
+
when you want a project that already mounts this.
|
|
40
|
+
|
|
41
|
+
## What the agent can do
|
|
42
|
+
|
|
43
|
+
With the extension mounted, the agent can consult a Grok Bot and stay
|
|
44
|
+
in its own conversation:
|
|
45
|
+
|
|
46
|
+
- **Ask.** Send a self-contained message to a Grok Bot by the name
|
|
47
|
+
shown in the Grok Bot app. The message lands in your conversation
|
|
48
|
+
with that bot. The tool waits for the bot's reply.
|
|
49
|
+
- **Keep waiting.** A long turn returns `status: "running"`. Call check
|
|
50
|
+
with the same name to read what arrived since the last look.
|
|
51
|
+
- **Stop a turn.** Interrupt the bot's current work. The conversation
|
|
52
|
+
stays; a later ask continues it.
|
|
53
|
+
- **See who you can talk to.** List the configured bots and the ones
|
|
54
|
+
this caller has already asked. Add a name to `agents` when you want
|
|
55
|
+
the model to reach another bot.
|
|
56
|
+
|
|
57
|
+
A skill teaches the model when to bring a Grok Bot in, how to write a
|
|
58
|
+
message the bot can act on alone, and how to wait or interrupt. The
|
|
59
|
+
reply is what the Grok Bot sent to the person. If a turn finishes with
|
|
60
|
+
no reply, the bot sent nothing; ask again with a clearer request, or
|
|
61
|
+
open the bot in the Grok Bot app.
|
|
62
|
+
|
|
63
|
+
The tools reach Grok Bot agents on the signed-in account. A bot another
|
|
64
|
+
user owns is out of reach. That separation is only as fine as your
|
|
65
|
+
host's auth; a shared bearer token or `--allow-anonymous` makes every
|
|
66
|
+
caller one principal, so use
|
|
67
|
+
[authored auth](../reference/channels.md#auth-policies) when callers
|
|
68
|
+
need their own.
|
|
69
|
+
|
|
70
|
+
## Configure it
|
|
71
|
+
|
|
72
|
+
| Option | What it controls |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `agents` | The Grok Bot agents the model may talk to, by the name shown in the app. A lone entry is the default when a call names none. Omit `agents` to allow any name; an unknown name creates an empty Grok Bot on the account. |
|
|
75
|
+
| `needsApproval` | Park asks for a [human decision](./human-in-the-loop.md). Defaults to `true` when no `agents` are configured, `false` otherwise. |
|
|
76
|
+
| `apiKey` | A Cursor API key to call with instead of the host's own. |
|
|
77
|
+
|
|
78
|
+
## Adjust it
|
|
79
|
+
|
|
80
|
+
To take a capability away, such as interrupting a turn, mount as a
|
|
81
|
+
directory and disable that tool; see
|
|
82
|
+
[overlays](../reference/extensions.md#adjust-a-mounted-extension).
|
|
83
|
+
|
|
84
|
+
## What's next
|
|
85
|
+
|
|
86
|
+
Continue with these pages:
|
|
87
|
+
|
|
88
|
+
- [Grok Bot agents template](../templates/grokbot-agents.md): scaffold
|
|
89
|
+
an agent that already mounts this
|
|
90
|
+
- [Extensions](../reference/extensions.md): how mounts, namespaces, and
|
|
91
|
+
overrides work
|
|
92
|
+
- [Human-in-the-loop approvals](./human-in-the-loop.md): where parked
|
|
93
|
+
asks get approved
|
|
@@ -92,10 +92,9 @@ is `serve({ otel })` over `agent/otel.ts` over env. An empty
|
|
|
92
92
|
`defineOtel()` still records traces; export starts when
|
|
93
93
|
`OTEL_EXPORTER_OTLP_*` or a factory-returned `exporters` list appears.
|
|
94
94
|
|
|
95
|
-
Hosted
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
queued batch.
|
|
95
|
+
Hosted deployments can bind secrets after startup. Pass a factory so
|
|
96
|
+
flush can re-read them. The hosted handler constructs the OTLP client
|
|
97
|
+
when it flushes and sends the queued batch.
|
|
99
98
|
|
|
100
99
|
```ts
|
|
101
100
|
export default defineOtel(() => resolveMyOtelConfig());
|
|
@@ -222,20 +222,16 @@ events. Declare `events` and handle each one in `onEvent`. Each event
|
|
|
222
222
|
carries `deploySourceUri` and `deployVersion`. Author
|
|
223
223
|
`agent/channels/deployments.ts` with `deploymentsChannel()`.
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
pull relay, which has no deploy scope to inherit. There, subscribe per
|
|
232
|
-
deploy source with `deploySourceUris` and narrow with `environments` /
|
|
233
|
-
`events`. Each entry must match `Deployment.deploy_source_uri` as your
|
|
234
|
-
deployment writer records it; matching is case-insensitive but
|
|
225
|
+
On Cursor-managed hosting, omit `deploySourceUris`. The deployment's
|
|
226
|
+
watched repositories bind the event scope automatically. Name sources
|
|
227
|
+
to narrow the scope or to drive the self-hosted pull relay. Subscribe
|
|
228
|
+
per deploy source with `deploySourceUris` and narrow with `environments`
|
|
229
|
+
or `events`. Each entry must match `Deployment.deploy_source_uri` as
|
|
230
|
+
your deployment writer records it. Matching is case-insensitive but
|
|
235
231
|
otherwise literal. It uses the host credential. A restart resumes
|
|
236
|
-
rather than dropping events. An empty `deploySourceUris` list mounts
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
rather than dropping events. An empty `deploySourceUris` list mounts the
|
|
233
|
+
channel but starts no pull, so an env-configured agent stays inert until
|
|
234
|
+
its deploy sources are set.
|
|
239
235
|
|
|
240
236
|
**Change Monitors** (`@cursor/july/channels/change-monitors`): Change
|
|
241
237
|
Monitor Checkpoint events. The channel publishes Factory
|
|
@@ -244,18 +240,14 @@ result (for example to the `issues` arm). The payload contains the
|
|
|
244
240
|
full Checkpoint resource. This channel is scoped to Change Monitors,
|
|
245
241
|
not generic Factory Checkpoints. There is no repository filter or
|
|
246
242
|
resource filter. Author `agent/channels/change-monitors.ts` with
|
|
247
|
-
`changeMonitorsChannel()`. It uses the host credential.
|
|
248
|
-
continuation is `none/v1`. A v2 agent defaults to
|
|
249
|
-
`change_monitors.checkpoint/v2`, which keys the session as
|
|
250
|
-
`cont:change_monitors:{checkpointName}`.
|
|
243
|
+
`changeMonitorsChannel()`. It uses the host credential.
|
|
251
244
|
|
|
252
245
|
**Issues** (`@cursor/july/channels/issues`): Factory issue events.
|
|
253
246
|
The channel publishes `issue.created` for every Issue create. The
|
|
254
247
|
agent filters if it needs a subset. The payload contains the full
|
|
255
248
|
Issue resource. There is no repository filter or resource filter.
|
|
256
249
|
Author `agent/channels/issues.ts` with `issuesChannel()`. It uses the
|
|
257
|
-
host credential.
|
|
258
|
-
defaults to `issues.issue/v2`, which keys the session by issue name.
|
|
250
|
+
host credential.
|
|
259
251
|
|
|
260
252
|
For other platforms like Discord or Teams, use the authored
|
|
261
253
|
`defineChannel` webhook form.
|
package/docs/reference/cli.md
CHANGED
|
@@ -414,6 +414,7 @@ non-zero when the reconstructed trajectory failed.
|
|
|
414
414
|
```bash
|
|
415
415
|
agent-sdk init ./my-agent # scaffold package.json, tsconfig.json, agent/ + a demo tool
|
|
416
416
|
agent-sdk init ./my-demo --template demo # record a PR walkthrough
|
|
417
|
+
agent-sdk init ./grokbot --template grokbot-agents # talk to Grok Bot agents
|
|
417
418
|
agent-sdk init ./code-wiki --template code-wiki # keep wiki pages current after merge
|
|
418
419
|
agent-sdk init ./agents-md --template agents-md # keep AGENTS.md current from last week's PRs and Slack
|
|
419
420
|
agent-sdk init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
@@ -435,7 +436,7 @@ agent-sdk init # no directory: print the setup guide
|
|
|
435
436
|
Templates may ship `init.json`. On a TTY, `init` asks those questions
|
|
436
437
|
before writing files. `code-wiki`, `pr-autofixer`, `security-help`, and
|
|
437
438
|
`agents-md` ask for GitHub repos. `agents-md` also asks for Slack
|
|
438
|
-
channels. Repeat
|
|
439
|
+
channels. `grokbot-agents` asks for Grok Bot names. Repeat
|
|
439
440
|
`--var id=value` to answer without a prompt.
|
|
440
441
|
`--json` and non-TTY hosts skip the interview unless `--var` is set.
|
|
441
442
|
|
|
@@ -673,14 +674,17 @@ The command polls for up to ten minutes until the status reaches
|
|
|
673
674
|
|
|
674
675
|
## delete
|
|
675
676
|
|
|
676
|
-
`delete` removes a deployment.
|
|
677
|
+
`delete` removes a hosted deployment. You can delete a deployment that
|
|
678
|
+
still runs. The command frees the slug. A later deploy can use the same
|
|
679
|
+
name. Spend stays on the archived service account.
|
|
677
680
|
|
|
678
681
|
```bash
|
|
679
682
|
agent-sdk delete <slug> [--team <id>] [--no-wait] [--json]
|
|
680
683
|
```
|
|
681
684
|
|
|
682
685
|
The command waits until the deployment is gone. `--no-wait` returns after
|
|
683
|
-
the delete request is accepted.
|
|
686
|
+
the delete request is accepted. Architecture v2 slugs use the Agent SDK
|
|
687
|
+
control plane. Architecture v1 slugs use the Agent Serve control plane.
|
|
684
688
|
|
|
685
689
|
## rotate-token
|
|
686
690
|
|
|
@@ -263,6 +263,8 @@ Continue with these pages:
|
|
|
263
263
|
|
|
264
264
|
- [Cursor cloud agents](../guides/cloud-agents.md): the extension that
|
|
265
265
|
lets an agent launch and steer cloud agents
|
|
266
|
+
- [Cursor Grok Bot agents](../guides/grokbot-agents.md): the extension
|
|
267
|
+
that lets an agent talk to Grok Bot agents
|
|
266
268
|
- [Tools](./tools.md): the tool contract extensions contribute to
|
|
267
269
|
- [Skills](./skills.md): the skill forms an extension can carry
|
|
268
270
|
- [Project layout](./project-layout.md): where `agent/extensions/` sits
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Talk to your Grok Bot agents"
|
|
3
|
+
description: "Scaffold the agent, name the Grok Bot agents it may reach, and consult them from its own conversation."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Talk to your Grok Bot agents
|
|
7
|
+
|
|
8
|
+
This agent sends a message to a Grok Bot you already use and reads the
|
|
9
|
+
reply. The Grok Bot keeps its conversation. This agent stays where it
|
|
10
|
+
is.
|
|
11
|
+
|
|
12
|
+
## Scaffold
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @cursor/july init ./grokbot --template grokbot-agents
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`init` asks for the names shown in the Grok Bot app. Every name is an
|
|
19
|
+
allowlist entry. Pass `--var agents="Plan Keeper, Chief of Staff"` to
|
|
20
|
+
skip the prompt.
|
|
21
|
+
|
|
22
|
+
The names land in `agent/extensions/grokbot.ts`. A name outside that
|
|
23
|
+
list is refused.
|
|
24
|
+
|
|
25
|
+
## Log in
|
|
26
|
+
|
|
27
|
+
Asks run under the signed-in account.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd grokbot
|
|
31
|
+
agent-sdk login
|
|
32
|
+
agent-sdk dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
In the playground, ask it to talk to one of the names you entered.
|
|
36
|
+
|
|
37
|
+
## What to edit
|
|
38
|
+
|
|
39
|
+
- `agent/extensions/grokbot.ts`: who it may talk to. Add `needsApproval: true` to park each ask.
|
|
40
|
+
- `agent/instructions.md`: when to consult them
|
|
41
|
+
|
|
42
|
+
See [Cursor Grok Bot agents](../guides/grokbot-agents.md) for the
|
|
43
|
+
extension, and [Human-in-the-loop approvals](../guides/human-in-the-loop.md)
|
|
44
|
+
for where a parked ask gets approved.
|
|
45
|
+
|
|
46
|
+
## Evals
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
agent-sdk eval
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The smoke case asks who it can talk to. It must list the configured
|
|
53
|
+
bots and not send a message.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cursor/july",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
4
4
|
"description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"repository": {
|
|
@@ -23,14 +23,16 @@
|
|
|
23
23
|
"!dist/playground-central/**",
|
|
24
24
|
"!dist/internal/tenant-mcp/**",
|
|
25
25
|
"!dist/internal/grokbot/**",
|
|
26
|
-
"!dist/
|
|
26
|
+
"!dist/extensions/cursor-grokbot-agents/**",
|
|
27
|
+
"!dist/internal/review-comments*",
|
|
27
28
|
"!dist/internal/shallow-clone.*",
|
|
28
29
|
"!dist/internal/managed-delivery.*",
|
|
29
30
|
"src/**/*",
|
|
30
31
|
"!src/**/*.test.ts",
|
|
31
32
|
"!src/internal/tenant-mcp/**",
|
|
32
33
|
"!src/internal/grokbot/**",
|
|
33
|
-
"!src/
|
|
34
|
+
"!src/extensions/cursor-grokbot-agents/**",
|
|
35
|
+
"!src/internal/review-comments*",
|
|
34
36
|
"!src/internal/shallow-clone.ts",
|
|
35
37
|
"!src/internal/managed-delivery.ts",
|
|
36
38
|
"skills/**/*",
|
|
@@ -137,6 +139,13 @@
|
|
|
137
139
|
"import": "./dist/extensions/cursor-cloud-agents/extension.js",
|
|
138
140
|
"default": "./dist/extensions/cursor-cloud-agents/extension.js"
|
|
139
141
|
},
|
|
142
|
+
"./extensions/cursor-grokbot-agents": {
|
|
143
|
+
"anysphere-source": "./src/extensions/cursor-grokbot-agents/extension.ts",
|
|
144
|
+
"bun": "./dist/extensions/cursor-grokbot-agents/extension.js",
|
|
145
|
+
"types": "./dist/extensions/cursor-grokbot-agents/extension.d.ts",
|
|
146
|
+
"import": "./dist/extensions/cursor-grokbot-agents/extension.js",
|
|
147
|
+
"default": "./dist/extensions/cursor-grokbot-agents/extension.js"
|
|
148
|
+
},
|
|
140
149
|
"./schedules": {
|
|
141
150
|
"anysphere-source": "./src/schedules.ts",
|
|
142
151
|
"types": "./dist/schedules.d.ts",
|
package/skills/otel/SKILL.md
CHANGED
|
@@ -33,9 +33,9 @@ export default defineOtel({
|
|
|
33
33
|
3. `serve(dir, { otel: { … } })`. `otel: false` disables env and
|
|
34
34
|
authored config.
|
|
35
35
|
|
|
36
|
-
Hosted
|
|
37
|
-
re-resolves exporters. Authored `agent/otel.ts` records from
|
|
38
|
-
start even when the factory returns no exporters yet.
|
|
36
|
+
Hosted secrets can arrive after startup. Use `defineOtel(() => …)` so
|
|
37
|
+
flush re-resolves exporters. Authored `agent/otel.ts` records from
|
|
38
|
+
process start even when the factory returns no exporters yet.
|
|
39
39
|
|
|
40
40
|
| Signal | Default |
|
|
41
41
|
| --- | --- |
|
package/src/bin/agent-serve.ts
CHANGED
|
@@ -341,9 +341,6 @@ Options:
|
|
|
341
341
|
the Cursor backend's per-forge forwarder instead of
|
|
342
342
|
minting raw tokens into this process
|
|
343
343
|
(AGENT_SERVE_<FORGE>_PROXY_URL overrides a base URL).
|
|
344
|
-
--cursor-github-proxy
|
|
345
|
-
serve: deprecated alias for --cursor-scm-proxy; removed
|
|
346
|
-
one release after --cursor-scm-proxy ships.
|
|
347
344
|
--public-url serve: base URL where this host is reachable from outside
|
|
348
345
|
(e.g. https://agent-serve.example.com). Required for peer
|
|
349
346
|
connections (defineConnection({ agent })) on cloud-runtime
|
|
@@ -519,7 +516,6 @@ async function main(argv: string[]): Promise<number> {
|
|
|
519
516
|
"allow-anonymous-cursor-account-mcp": { type: "boolean", default: false },
|
|
520
517
|
"allow-anonymous-grokbot": { type: "boolean", default: false },
|
|
521
518
|
"cursor-scm-proxy": { type: "boolean", default: false },
|
|
522
|
-
"cursor-github-proxy": { type: "boolean", default: false },
|
|
523
519
|
"no-schedules": { type: "boolean", default: false },
|
|
524
520
|
"no-control-plane": { type: "boolean", default: false },
|
|
525
521
|
"no-playground": { type: "boolean", default: false },
|
|
@@ -1353,11 +1349,7 @@ async function main(argv: string[]): Promise<number> {
|
|
|
1353
1349
|
: undefined,
|
|
1354
1350
|
allowAnonymousGrokbot:
|
|
1355
1351
|
values["allow-anonymous-grokbot"] === true ? true : undefined,
|
|
1356
|
-
cursorScmProxy:
|
|
1357
|
-
values["cursor-scm-proxy"] === true ||
|
|
1358
|
-
values["cursor-github-proxy"] === true
|
|
1359
|
-
? true
|
|
1360
|
-
: undefined,
|
|
1352
|
+
cursorScmProxy: values["cursor-scm-proxy"] === true ? true : undefined,
|
|
1361
1353
|
schedules: values["no-schedules"] === true ? false : undefined,
|
|
1362
1354
|
noControlPlane: values["no-control-plane"] === true ? true : undefined,
|
|
1363
1355
|
playground: values["no-playground"] === true ? false : undefined,
|
|
@@ -229,10 +229,8 @@ export interface BitbucketChannelOptions {
|
|
|
229
229
|
*/
|
|
230
230
|
webhookEvents?: readonly string[];
|
|
231
231
|
/**
|
|
232
|
-
* Continuation selector.
|
|
233
|
-
*
|
|
234
|
-
* `architecture: "v2"` (then `bitbucket.pr/v2`, or `bitbucket.none/v2`
|
|
235
|
-
* when a non-PR event is declared).
|
|
232
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
233
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
236
234
|
*/
|
|
237
235
|
continuation?: ContinuationIdentity;
|
|
238
236
|
/**
|
|
@@ -25,6 +25,7 @@ const deploymentEventSchema = z.object({
|
|
|
25
25
|
environment: z.string().min(1),
|
|
26
26
|
service: z.string().min(1).optional(),
|
|
27
27
|
deployVersion: z.string().min(1),
|
|
28
|
+
previousVersion: z.string().min(1).optional(),
|
|
28
29
|
status: z.enum(["pending", "in_progress", "success", "failed"]),
|
|
29
30
|
occurredAtMs: z.number(),
|
|
30
31
|
});
|
|
@@ -28,6 +28,8 @@ export interface DeploymentEvent {
|
|
|
28
28
|
/** Absent when the deployment records no service. */
|
|
29
29
|
service?: string;
|
|
30
30
|
deployVersion: string;
|
|
31
|
+
/** Last succeeded different SHA; omitted on the first ship. */
|
|
32
|
+
previousVersion?: string;
|
|
31
33
|
status: DeploymentStatus;
|
|
32
34
|
occurredAtMs: number;
|
|
33
35
|
}
|
|
@@ -54,10 +56,9 @@ export interface DeploymentsChannelOptions {
|
|
|
54
56
|
* and then receives nothing. A bare string takes the default environment and
|
|
55
57
|
* event filters.
|
|
56
58
|
*
|
|
57
|
-
* Omit on
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* sources for a tenant it has never seen.
|
|
59
|
+
* Omit on Cursor-managed hosting. The control plane binds sources from the
|
|
60
|
+
* deployment's watched repositories, and the channel admits only what it
|
|
61
|
+
* receives. An agent cannot enumerate sources for an unseen tenant.
|
|
61
62
|
*
|
|
62
63
|
* Name sources to narrow below that scope, or to drive the self-hosted
|
|
63
64
|
* relay, which has no deploy scope to inherit. On that wire `[]` means
|
|
@@ -87,10 +88,8 @@ export interface DeploymentsChannelOptions {
|
|
|
87
88
|
onStart?: ChannelDefinition["onStart"];
|
|
88
89
|
onStop?: ChannelDefinition["onStop"];
|
|
89
90
|
/**
|
|
90
|
-
* Continuation selector.
|
|
91
|
-
*
|
|
92
|
-
* `"deployments.deployment/v2"`). Override with `"deployments.none/v2"`
|
|
93
|
-
* for one-shot events.
|
|
91
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
92
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
94
93
|
*/
|
|
95
94
|
continuation?: ContinuationIdentity;
|
|
96
95
|
}
|
|
@@ -480,10 +480,8 @@ export interface GitHubChannelOptions {
|
|
|
480
480
|
*/
|
|
481
481
|
botName?: string;
|
|
482
482
|
/**
|
|
483
|
-
* Continuation selector.
|
|
484
|
-
*
|
|
485
|
-
* `"github.pr/v2"`). Override type with `"github.issue/v2"` or
|
|
486
|
-
* `"github.none/v2"` for events outside PR membership.
|
|
483
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
484
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
487
485
|
*/
|
|
488
486
|
continuation?: ContinuationIdentity;
|
|
489
487
|
/**
|
|
@@ -219,11 +219,8 @@ export interface GitLabChannelOptions {
|
|
|
219
219
|
*/
|
|
220
220
|
webhookEvents?: readonly string[];
|
|
221
221
|
/**
|
|
222
|
-
* Continuation selector.
|
|
223
|
-
*
|
|
224
|
-
* `architecture: "v2"` (then `gitlab.mr/v2`, or `gitlab.none/v2` when a
|
|
225
|
-
* non-MR event is declared). Override with `"gitlab.none/v2"` for one-shot
|
|
226
|
-
* events.
|
|
222
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
223
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
227
224
|
*/
|
|
228
225
|
continuation?: ContinuationIdentity;
|
|
229
226
|
/**
|
|
@@ -246,9 +246,8 @@ export interface OriginChannelOptions {
|
|
|
246
246
|
*/
|
|
247
247
|
webhookEvents?: readonly string[];
|
|
248
248
|
/**
|
|
249
|
-
* Continuation selector.
|
|
250
|
-
*
|
|
251
|
-
* `"origin.pr/v2"`). Override with `"origin.none/v2"` for one-shot events.
|
|
249
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
250
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
252
251
|
*/
|
|
253
252
|
continuation?: ContinuationIdentity;
|
|
254
253
|
/**
|
|
@@ -362,6 +362,9 @@ export function buildDefaultEvents(
|
|
|
362
362
|
channel.state.streamTs = null;
|
|
363
363
|
channel.state.streamChannelId = null;
|
|
364
364
|
channel.state.streamFull = false;
|
|
365
|
+
// A stream failure downgrades the rest of its own turn, not the thread.
|
|
366
|
+
channel.state.streamingUnavailable = false;
|
|
367
|
+
channel.state.streamAppendedChunks = 0;
|
|
365
368
|
channel.state.lastPostedText = null;
|
|
366
369
|
channel.state.streamBlockText = null;
|
|
367
370
|
channel.state.reasoningCard = undefined;
|
|
@@ -147,6 +147,7 @@ export function createStreamDeliveryStrategy(
|
|
|
147
147
|
channel.state.streamTs = started.ts;
|
|
148
148
|
channel.state.streamChannelId = started.channel;
|
|
149
149
|
channel.state.streamFull = false;
|
|
150
|
+
channel.state.streamAppendedChunks = 0;
|
|
150
151
|
channel.state.lastPostedText = openingText;
|
|
151
152
|
channel.state.streamBlockText = openingText;
|
|
152
153
|
log.info("chat.startStream ok", {
|
|
@@ -193,6 +194,21 @@ export function createStreamDeliveryStrategy(
|
|
|
193
194
|
highlightCodeFences(text)
|
|
194
195
|
);
|
|
195
196
|
|
|
197
|
+
/**
|
|
198
|
+
* The reply does not extend what the stream already holds, so there is no
|
|
199
|
+
* delta to append and the text on Slack is not the reply.
|
|
200
|
+
*/
|
|
201
|
+
const rewound = (channel: SlackChannel, text: string): boolean =>
|
|
202
|
+
streamDelta(channel, text) === "" &&
|
|
203
|
+
!highlightCodeFences(text).startsWith(
|
|
204
|
+
highlightCodeFences(channel.state.streamBlockText ?? "")
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const countAppended = (channel: SlackChannel, chunks: number): void => {
|
|
208
|
+
channel.state.streamAppendedChunks =
|
|
209
|
+
(channel.state.streamAppendedChunks ?? 0) + chunks;
|
|
210
|
+
};
|
|
211
|
+
|
|
196
212
|
const stopWithSuffix = async (args: {
|
|
197
213
|
channel: SlackChannel;
|
|
198
214
|
channelId: string;
|
|
@@ -246,25 +262,25 @@ export function createStreamDeliveryStrategy(
|
|
|
246
262
|
};
|
|
247
263
|
|
|
248
264
|
/**
|
|
249
|
-
* The
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
* duplicate would be worse than a lost tail.
|
|
265
|
+
* The open stream cannot carry the rest of the reply — it is full, or the
|
|
266
|
+
* reply no longer extends what it holds. Close it as it stands so it stops
|
|
267
|
+
* spinning and post the remainder as a new thread message.
|
|
253
268
|
*/
|
|
254
|
-
const
|
|
269
|
+
const continueInNewMessage = async (args: {
|
|
255
270
|
channel: SlackChannel;
|
|
256
271
|
channelId: string;
|
|
257
272
|
ts: string;
|
|
258
273
|
remainder: string;
|
|
274
|
+
reason: string;
|
|
259
275
|
sessionId: string;
|
|
260
|
-
}): Promise<
|
|
261
|
-
const { channel, channelId, ts, remainder, sessionId } = args;
|
|
276
|
+
}): Promise<boolean> => {
|
|
277
|
+
const { channel, channelId, ts, remainder, reason, sessionId } = args;
|
|
262
278
|
const log = getLog();
|
|
263
279
|
await stopChatStream({ botToken, channel: channelId, ts });
|
|
264
280
|
channel.state.streamTs = null;
|
|
265
281
|
const threadTs = channel.state.threadTs;
|
|
266
282
|
if (remainder === "" || threadTs === null || threadTs === "") {
|
|
267
|
-
return;
|
|
283
|
+
return true;
|
|
268
284
|
}
|
|
269
285
|
try {
|
|
270
286
|
const posted = await postMessage({
|
|
@@ -275,19 +291,23 @@ export function createStreamDeliveryStrategy(
|
|
|
275
291
|
plainText: remainder.length >= SLACK_MARKDOWN_TEXT_MAX_LEN,
|
|
276
292
|
});
|
|
277
293
|
channel.state.lastBotMessageTs = posted.ts;
|
|
278
|
-
log.info("reply
|
|
294
|
+
log.info("reply continued in a new message", {
|
|
295
|
+
reason,
|
|
279
296
|
channel: channelId,
|
|
280
297
|
stream_ts: ts,
|
|
281
298
|
session: sessionId,
|
|
282
299
|
continued_chars: remainder.length,
|
|
283
300
|
});
|
|
301
|
+
return true;
|
|
284
302
|
} catch (error) {
|
|
285
|
-
log.warn("stream
|
|
303
|
+
log.warn("stream continuation failed", {
|
|
304
|
+
reason,
|
|
286
305
|
error: error instanceof Error ? error.message : String(error),
|
|
287
306
|
channel: channelId,
|
|
288
307
|
stream_ts: ts,
|
|
289
308
|
session: sessionId,
|
|
290
309
|
});
|
|
310
|
+
return false;
|
|
291
311
|
}
|
|
292
312
|
};
|
|
293
313
|
|
|
@@ -328,6 +348,7 @@ export function createStreamDeliveryStrategy(
|
|
|
328
348
|
noteAppendFailure(channel, result);
|
|
329
349
|
return;
|
|
330
350
|
}
|
|
351
|
+
countAppended(channel, 1);
|
|
331
352
|
channel.state.lastPostedText = text;
|
|
332
353
|
channel.state.streamBlockText = text;
|
|
333
354
|
},
|
|
@@ -364,8 +385,10 @@ export function createStreamDeliveryStrategy(
|
|
|
364
385
|
chunks: chunks.length,
|
|
365
386
|
});
|
|
366
387
|
noteAppendFailure(channel, result);
|
|
388
|
+
return false;
|
|
367
389
|
}
|
|
368
|
-
|
|
390
|
+
countAppended(channel, chunks.length);
|
|
391
|
+
return true;
|
|
369
392
|
},
|
|
370
393
|
|
|
371
394
|
async finalize({ channel, channelId, text, sessionId }) {
|
|
@@ -381,6 +404,22 @@ export function createStreamDeliveryStrategy(
|
|
|
381
404
|
}
|
|
382
405
|
// Measured before the stop attempt mutates stream state.
|
|
383
406
|
const remainder = streamDelta(channel, text);
|
|
407
|
+
// Nothing to append and the stream does not hold the reply: closing it
|
|
408
|
+
// here would leave the answer nowhere and report it as delivered.
|
|
409
|
+
if (rewound(channel, text)) {
|
|
410
|
+
const posted = await continueInNewMessage({
|
|
411
|
+
channel,
|
|
412
|
+
channelId,
|
|
413
|
+
ts,
|
|
414
|
+
remainder: text,
|
|
415
|
+
reason: "rewound",
|
|
416
|
+
sessionId,
|
|
417
|
+
});
|
|
418
|
+
if (posted) {
|
|
419
|
+
channel.state.lastPostedText = text;
|
|
420
|
+
}
|
|
421
|
+
return { delivered: posted };
|
|
422
|
+
}
|
|
384
423
|
const stopped =
|
|
385
424
|
channel.state.streamFull === true
|
|
386
425
|
? { ok: false, error: "msg_too_long" }
|
|
@@ -391,15 +430,17 @@ export function createStreamDeliveryStrategy(
|
|
|
391
430
|
stream_ts: ts,
|
|
392
431
|
session: sessionId,
|
|
393
432
|
chars: text.length,
|
|
433
|
+
appends: channel.state.streamAppendedChunks ?? 0,
|
|
394
434
|
});
|
|
395
435
|
return { delivered: true };
|
|
396
436
|
}
|
|
397
437
|
if (stopped.error === "msg_too_long") {
|
|
398
|
-
await
|
|
438
|
+
await continueInNewMessage({
|
|
399
439
|
channel,
|
|
400
440
|
channelId,
|
|
401
441
|
ts,
|
|
402
442
|
remainder,
|
|
443
|
+
reason: "msg_too_long",
|
|
403
444
|
sessionId,
|
|
404
445
|
});
|
|
405
446
|
channel.state.lastPostedText = text;
|
|
@@ -81,6 +81,8 @@ export interface SlackChannelState {
|
|
|
81
81
|
streamingUnavailable?: boolean;
|
|
82
82
|
/** The open stream hit Slack's size cap; appends stop until it closes. */
|
|
83
83
|
streamFull?: boolean;
|
|
84
|
+
/** Chunks Slack accepted on the open stream, reported when it closes. */
|
|
85
|
+
streamAppendedChunks?: number;
|
|
84
86
|
/** Editable progress message ts when `chat.startStream` is unavailable. */
|
|
85
87
|
progressTs: string | null;
|
|
86
88
|
/**
|
|
@@ -597,9 +599,8 @@ export interface SlackAccessPolicy {
|
|
|
597
599
|
export interface SlackChannelOptions {
|
|
598
600
|
credentials?: SlackCredentials;
|
|
599
601
|
/**
|
|
600
|
-
* Continuation selector.
|
|
601
|
-
*
|
|
602
|
-
* `"slack.thread/v2"`). Override with `"slack.none/v2"` for one-shot events.
|
|
602
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
603
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
603
604
|
*/
|
|
604
605
|
continuation?: ContinuationIdentity;
|
|
605
606
|
/** Defaults to `{ respondTo: "thread", blockExternals: true }`. */
|