switchroom 0.15.11 → 0.15.13
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/agent-scheduler/index.js +16 -0
- package/dist/auth-broker/index.js +16 -0
- package/dist/cli/notion-write-pretool.mjs +16 -0
- package/dist/cli/switchroom.js +356 -186
- package/dist/host-control/main.js +16 -0
- package/dist/vault/approvals/kernel-server.js +16 -0
- package/dist/vault/broker/server.js +16 -0
- package/package.json +1 -1
- package/profiles/_shared/agent-self-service.md.hbs +37 -0
- package/telegram-plugin/bridge/bridge.ts +55 -0
- package/telegram-plugin/dist/bridge/bridge.js +53 -0
- package/telegram-plugin/dist/gateway/gateway.js +628 -50
- package/telegram-plugin/dist/server.js +53 -0
- package/telegram-plugin/gateway/gateway.ts +130 -5
- package/telegram-plugin/gateway/linear-activity.ts +305 -0
- package/telegram-plugin/gateway/model-command.ts +13 -5
- package/telegram-plugin/scoped-approval.ts +253 -0
- package/telegram-plugin/tests/gateway-request-secret.test.ts +1 -1
- package/telegram-plugin/tests/linear-agent-activity.test.ts +124 -0
- package/telegram-plugin/tests/linear-create-issue.test.ts +211 -0
- package/telegram-plugin/tests/model-command.test.ts +40 -0
- package/telegram-plugin/tests/permission-verdict-resume-guard.test.ts +13 -0
- package/telegram-plugin/tests/scoped-approval.test.ts +254 -0
|
@@ -13882,6 +13882,12 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
13882
13882
|
}).optional().describe("Per-source rate limit for the webhook ingest path (#714). " + "Off by default — when this key is absent the handler skips " + "rate-limit checks entirely. Opt in by setting `rpm` to an " + "integer requests-per-minute (token bucket per (agent, source); " + "burst equal to rpm). When enabled, exceeding the limit returns " + "429 with Retry-After header; first throttle event per " + "(agent, source) per 60s window is written to " + "<agent>/telegram/issues.jsonl. " + "Cascades from defaults.channels.telegram.webhook_rate_limit."),
|
|
13883
13883
|
webhook_via_gateway: exports_external.boolean().optional().describe("Route verified webhook events to the agent's in-container gateway " + "over a peercred-gated UDS (<agent>/telegram/webhook.sock) instead " + "of having the host-side web receiver write the agent dir directly. " + "Required under the Docker runtime: the receiver runs as the host " + "operator UID and cannot write the per-agent-UID-owned agent dir " + "(EACCES 500) nor connect the gateway socket. When true the gateway " + "(running as the agent UID) becomes the sole writer of " + "webhook-events.jsonl + dedup/cooldown state and also fires " + "webhook_dispatch. Off by default for back-compat with host-runtime " + "installs. See docs/rfcs/webhook-via-gateway-socket.md."),
|
|
13884
13884
|
webhook_require_edge: exports_external.boolean().optional().describe("Cloudflare-only edge lock: require the X-Switchroom-Edge header " + "(injected by a Cloudflare Transform Rule on hooks.switchroom.ai) to " + "match the operator's edge secret at ~/.switchroom/webhook-edge-secret " + "before any HMAC verification; reject 403 otherwise. Proves the " + "request entered through our Cloudflare edge — the per-agent HMAC " + "alone can't (it proves body provenance, not network path). Stacks " + "on the GitHub-IP WAF + per-agent HMAC. Fail-closed: when required " + "but the secret file is missing/empty every request is rejected. Off " + "by default. See docs/rfcs/webhook-cloudflare-edge-lock.md."),
|
|
13885
|
+
linear_agent: exports_external.object({
|
|
13886
|
+
enabled: exports_external.boolean(),
|
|
13887
|
+
token: exports_external.string().describe("vault:<key> reference to the Linear OAuth app token (actor=app). " + "Resolved at runtime via the vault broker (canonically " + "vault:linear/<agent>/token). Never an inline literal."),
|
|
13888
|
+
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational — used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace."),
|
|
13889
|
+
default_team_id: exports_external.string().optional().describe("Optional Linear team id new captured issues file into when the " + "agent doesn't pass an explicit team_id. Unnecessary for a " + "single-team workspace (auto-resolved); set it only when the " + "workspace has multiple teams. Manage via " + "`switchroom linear-agent set-team <agent> <team>`.")
|
|
13890
|
+
}).optional().describe("Linear first-class agent integration (#2298). When enabled, the " + "agent appears in a Linear workspace as an app actor (own name/" + "avatar, @-mentionable, delegate-assignable). Linear AgentSessionEvent " + "webhooks (mention / delegation) wake the agent instantly via the " + "same gateway inject path as webhook_dispatch, tagged " + 'meta.source="linear" with the agent_session_id, and the agent ' + "responds with structured AgentActivity (thought/message/complete/" + "error) via the linear_agent_activity MCP tool. Builds the " + "session-lifecycle layer on top of the plain webhook_sources:[linear] " + "+ webhook_dispatch support (#2272). The OAuth app token is stored in " + "the vault and referenced here as vault:linear/<agent>/token; run " + "`switchroom linear-agent setup <agent>` to provision it. Off by " + "default — opt in per agent. Cascades from " + "defaults.channels.telegram.linear_agent."),
|
|
13885
13891
|
chat_id: exports_external.string().regex(/^-\d+$/, 'supergroup chat_id must be a negative integer as a string (e.g. "-1001234567890")').optional().describe("Per-agent supergroup ID — overrides fleet `telegram.forum_chat_id`. " + "When set, requires `default_topic_id`. Negative integer as string. " + "Forbidden when `dm_only: true`. See docs/rfcs/supergroup-mode.md."),
|
|
13886
13892
|
default_topic_id: exports_external.number().int().positive().optional().describe("Forum topic ID this agent's automated outbounds default to when " + "no more-specific alias resolves. Defaults to General (topic 1) when " + "`chat_id` is set and this is omitted — set it only to pin a different " + "fallback topic. " + "Telegram's General topic is `id=1` at MTProto but sends omit the " + "field — the outbound wrapper strips `message_thread_id === 1` " + "on send. Forbidden when `dm_only: true`."),
|
|
13887
13893
|
topic_aliases: exports_external.record(exports_external.string(), exports_external.number().int().positive()).optional().describe("Operator-friendly names for forum topic IDs (e.g. " + "`{ general: 1, planning: 17, cron: 23, admin: 31, alerts: 41 }`). " + "Referenced from per-cron `topic:` fields and the outbound router " + "for autonomous events (boot → alerts, hostd → admin, etc.). " + "Cascades per-key through defaults → profile → agent.")
|
|
@@ -14764,6 +14770,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
14764
14770
|
}
|
|
14765
14771
|
merged.reaction_dispatch = combined;
|
|
14766
14772
|
}
|
|
14773
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
14774
|
+
if (linearEnabled) {
|
|
14775
|
+
const rd = merged.reaction_dispatch;
|
|
14776
|
+
if (!rd || rd.emojis === undefined) {
|
|
14777
|
+
merged.reaction_dispatch = {
|
|
14778
|
+
enabled: rd?.enabled ?? true,
|
|
14779
|
+
emojis: ["\uD83D\uDC68\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
14780
|
+
};
|
|
14781
|
+
}
|
|
14782
|
+
}
|
|
14767
14783
|
if (defaults.resources || merged.resources) {
|
|
14768
14784
|
const d = defaults.resources ?? {};
|
|
14769
14785
|
const a = merged.resources ?? {};
|
|
@@ -4305,6 +4305,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
4305
4305
|
}
|
|
4306
4306
|
merged.reaction_dispatch = combined;
|
|
4307
4307
|
}
|
|
4308
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
4309
|
+
if (linearEnabled) {
|
|
4310
|
+
const rd = merged.reaction_dispatch;
|
|
4311
|
+
if (!rd || rd.emojis === undefined) {
|
|
4312
|
+
merged.reaction_dispatch = {
|
|
4313
|
+
enabled: rd?.enabled ?? true,
|
|
4314
|
+
emojis: ["\uD83D\uDC68\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
4315
|
+
};
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4308
4318
|
if (defaults.resources || merged.resources) {
|
|
4309
4319
|
const d = defaults.resources ?? {};
|
|
4310
4320
|
const a = merged.resources ?? {};
|
|
@@ -11480,6 +11490,12 @@ var init_schema = __esm(() => {
|
|
|
11480
11490
|
}).optional().describe("Per-source rate limit for the webhook ingest path (#714). " + "Off by default — when this key is absent the handler skips " + "rate-limit checks entirely. Opt in by setting `rpm` to an " + "integer requests-per-minute (token bucket per (agent, source); " + "burst equal to rpm). When enabled, exceeding the limit returns " + "429 with Retry-After header; first throttle event per " + "(agent, source) per 60s window is written to " + "<agent>/telegram/issues.jsonl. " + "Cascades from defaults.channels.telegram.webhook_rate_limit."),
|
|
11481
11491
|
webhook_via_gateway: exports_external.boolean().optional().describe("Route verified webhook events to the agent's in-container gateway " + "over a peercred-gated UDS (<agent>/telegram/webhook.sock) instead " + "of having the host-side web receiver write the agent dir directly. " + "Required under the Docker runtime: the receiver runs as the host " + "operator UID and cannot write the per-agent-UID-owned agent dir " + "(EACCES 500) nor connect the gateway socket. When true the gateway " + "(running as the agent UID) becomes the sole writer of " + "webhook-events.jsonl + dedup/cooldown state and also fires " + "webhook_dispatch. Off by default for back-compat with host-runtime " + "installs. See docs/rfcs/webhook-via-gateway-socket.md."),
|
|
11482
11492
|
webhook_require_edge: exports_external.boolean().optional().describe("Cloudflare-only edge lock: require the X-Switchroom-Edge header " + "(injected by a Cloudflare Transform Rule on hooks.switchroom.ai) to " + "match the operator's edge secret at ~/.switchroom/webhook-edge-secret " + "before any HMAC verification; reject 403 otherwise. Proves the " + "request entered through our Cloudflare edge — the per-agent HMAC " + "alone can't (it proves body provenance, not network path). Stacks " + "on the GitHub-IP WAF + per-agent HMAC. Fail-closed: when required " + "but the secret file is missing/empty every request is rejected. Off " + "by default. See docs/rfcs/webhook-cloudflare-edge-lock.md."),
|
|
11493
|
+
linear_agent: exports_external.object({
|
|
11494
|
+
enabled: exports_external.boolean(),
|
|
11495
|
+
token: exports_external.string().describe("vault:<key> reference to the Linear OAuth app token (actor=app). " + "Resolved at runtime via the vault broker (canonically " + "vault:linear/<agent>/token). Never an inline literal."),
|
|
11496
|
+
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational — used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace."),
|
|
11497
|
+
default_team_id: exports_external.string().optional().describe("Optional Linear team id new captured issues file into when the " + "agent doesn't pass an explicit team_id. Unnecessary for a " + "single-team workspace (auto-resolved); set it only when the " + "workspace has multiple teams. Manage via " + "`switchroom linear-agent set-team <agent> <team>`.")
|
|
11498
|
+
}).optional().describe("Linear first-class agent integration (#2298). When enabled, the " + "agent appears in a Linear workspace as an app actor (own name/" + "avatar, @-mentionable, delegate-assignable). Linear AgentSessionEvent " + "webhooks (mention / delegation) wake the agent instantly via the " + "same gateway inject path as webhook_dispatch, tagged " + 'meta.source="linear" with the agent_session_id, and the agent ' + "responds with structured AgentActivity (thought/message/complete/" + "error) via the linear_agent_activity MCP tool. Builds the " + "session-lifecycle layer on top of the plain webhook_sources:[linear] " + "+ webhook_dispatch support (#2272). The OAuth app token is stored in " + "the vault and referenced here as vault:linear/<agent>/token; run " + "`switchroom linear-agent setup <agent>` to provision it. Off by " + "default — opt in per agent. Cascades from " + "defaults.channels.telegram.linear_agent."),
|
|
11483
11499
|
chat_id: exports_external.string().regex(/^-\d+$/, 'supergroup chat_id must be a negative integer as a string (e.g. "-1001234567890")').optional().describe("Per-agent supergroup ID — overrides fleet `telegram.forum_chat_id`. " + "When set, requires `default_topic_id`. Negative integer as string. " + "Forbidden when `dm_only: true`. See docs/rfcs/supergroup-mode.md."),
|
|
11484
11500
|
default_topic_id: exports_external.number().int().positive().optional().describe("Forum topic ID this agent's automated outbounds default to when " + "no more-specific alias resolves. Defaults to General (topic 1) when " + "`chat_id` is set and this is omitted — set it only to pin a different " + "fallback topic. " + "Telegram's General topic is `id=1` at MTProto but sends omit the " + "field — the outbound wrapper strips `message_thread_id === 1` " + "on send. Forbidden when `dm_only: true`."),
|
|
11485
11501
|
topic_aliases: exports_external.record(exports_external.string(), exports_external.number().int().positive()).optional().describe("Operator-friendly names for forum topic IDs (e.g. " + "`{ general: 1, planning: 17, cron: 23, admin: 31, alerts: 41 }`). " + "Referenced from per-cron `topic:` fields and the outbound router " + "for autonomous events (boot → alerts, hostd → admin, etc.). " + "Cascades per-key through defaults → profile → agent.")
|
|
@@ -339,6 +339,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
339
339
|
}
|
|
340
340
|
merged.reaction_dispatch = combined;
|
|
341
341
|
}
|
|
342
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
343
|
+
if (linearEnabled) {
|
|
344
|
+
const rd = merged.reaction_dispatch;
|
|
345
|
+
if (!rd || rd.emojis === undefined) {
|
|
346
|
+
merged.reaction_dispatch = {
|
|
347
|
+
enabled: rd?.enabled ?? true,
|
|
348
|
+
emojis: ["\uD83D\uDC68\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
342
352
|
if (defaults.resources || merged.resources) {
|
|
343
353
|
const d = defaults.resources ?? {};
|
|
344
354
|
const a = merged.resources ?? {};
|
|
@@ -11480,6 +11490,12 @@ var init_schema = __esm(() => {
|
|
|
11480
11490
|
}).optional().describe("Per-source rate limit for the webhook ingest path (#714). " + "Off by default — when this key is absent the handler skips " + "rate-limit checks entirely. Opt in by setting `rpm` to an " + "integer requests-per-minute (token bucket per (agent, source); " + "burst equal to rpm). When enabled, exceeding the limit returns " + "429 with Retry-After header; first throttle event per " + "(agent, source) per 60s window is written to " + "<agent>/telegram/issues.jsonl. " + "Cascades from defaults.channels.telegram.webhook_rate_limit."),
|
|
11481
11491
|
webhook_via_gateway: exports_external.boolean().optional().describe("Route verified webhook events to the agent's in-container gateway " + "over a peercred-gated UDS (<agent>/telegram/webhook.sock) instead " + "of having the host-side web receiver write the agent dir directly. " + "Required under the Docker runtime: the receiver runs as the host " + "operator UID and cannot write the per-agent-UID-owned agent dir " + "(EACCES 500) nor connect the gateway socket. When true the gateway " + "(running as the agent UID) becomes the sole writer of " + "webhook-events.jsonl + dedup/cooldown state and also fires " + "webhook_dispatch. Off by default for back-compat with host-runtime " + "installs. See docs/rfcs/webhook-via-gateway-socket.md."),
|
|
11482
11492
|
webhook_require_edge: exports_external.boolean().optional().describe("Cloudflare-only edge lock: require the X-Switchroom-Edge header " + "(injected by a Cloudflare Transform Rule on hooks.switchroom.ai) to " + "match the operator's edge secret at ~/.switchroom/webhook-edge-secret " + "before any HMAC verification; reject 403 otherwise. Proves the " + "request entered through our Cloudflare edge — the per-agent HMAC " + "alone can't (it proves body provenance, not network path). Stacks " + "on the GitHub-IP WAF + per-agent HMAC. Fail-closed: when required " + "but the secret file is missing/empty every request is rejected. Off " + "by default. See docs/rfcs/webhook-cloudflare-edge-lock.md."),
|
|
11493
|
+
linear_agent: exports_external.object({
|
|
11494
|
+
enabled: exports_external.boolean(),
|
|
11495
|
+
token: exports_external.string().describe("vault:<key> reference to the Linear OAuth app token (actor=app). " + "Resolved at runtime via the vault broker (canonically " + "vault:linear/<agent>/token). Never an inline literal."),
|
|
11496
|
+
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational — used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace."),
|
|
11497
|
+
default_team_id: exports_external.string().optional().describe("Optional Linear team id new captured issues file into when the " + "agent doesn't pass an explicit team_id. Unnecessary for a " + "single-team workspace (auto-resolved); set it only when the " + "workspace has multiple teams. Manage via " + "`switchroom linear-agent set-team <agent> <team>`.")
|
|
11498
|
+
}).optional().describe("Linear first-class agent integration (#2298). When enabled, the " + "agent appears in a Linear workspace as an app actor (own name/" + "avatar, @-mentionable, delegate-assignable). Linear AgentSessionEvent " + "webhooks (mention / delegation) wake the agent instantly via the " + "same gateway inject path as webhook_dispatch, tagged " + 'meta.source="linear" with the agent_session_id, and the agent ' + "responds with structured AgentActivity (thought/message/complete/" + "error) via the linear_agent_activity MCP tool. Builds the " + "session-lifecycle layer on top of the plain webhook_sources:[linear] " + "+ webhook_dispatch support (#2272). The OAuth app token is stored in " + "the vault and referenced here as vault:linear/<agent>/token; run " + "`switchroom linear-agent setup <agent>` to provision it. Off by " + "default — opt in per agent. Cascades from " + "defaults.channels.telegram.linear_agent."),
|
|
11483
11499
|
chat_id: exports_external.string().regex(/^-\d+$/, 'supergroup chat_id must be a negative integer as a string (e.g. "-1001234567890")').optional().describe("Per-agent supergroup ID — overrides fleet `telegram.forum_chat_id`. " + "When set, requires `default_topic_id`. Negative integer as string. " + "Forbidden when `dm_only: true`. See docs/rfcs/supergroup-mode.md."),
|
|
11484
11500
|
default_topic_id: exports_external.number().int().positive().optional().describe("Forum topic ID this agent's automated outbounds default to when " + "no more-specific alias resolves. Defaults to General (topic 1) when " + "`chat_id` is set and this is omitted — set it only to pin a different " + "fallback topic. " + "Telegram's General topic is `id=1` at MTProto but sends omit the " + "field — the outbound wrapper strips `message_thread_id === 1` " + "on send. Forbidden when `dm_only: true`."),
|
|
11485
11501
|
topic_aliases: exports_external.record(exports_external.string(), exports_external.number().int().positive()).optional().describe("Operator-friendly names for forum topic IDs (e.g. " + "`{ general: 1, planning: 17, cron: 23, admin: 31, alerts: 41 }`). " + "Referenced from per-cron `topic:` fields and the outbound router " + "for autonomous events (boot → alerts, hostd → admin, etc.). " + "Cascades per-key through defaults → profile → agent.")
|
package/package.json
CHANGED
|
@@ -123,6 +123,43 @@ After a successful `schedule_add`, confirm to the user with:
|
|
|
123
123
|
After a failed write (any `E_*` code from the rails above), surface the
|
|
124
124
|
specific error verbatim, explain which rail tripped, and offer the
|
|
125
125
|
closest legal alternative.
|
|
126
|
+
{{#if linearAgentEnabled}}
|
|
127
|
+
|
|
128
|
+
## Capture to Linear (👨💻 / 📌 reaction → new issue)
|
|
129
|
+
|
|
130
|
+
You're connected to Linear as a first-class app actor. The operator has the
|
|
131
|
+
**capture reactions** wired: when they react to a Telegram message with **👨💻**
|
|
132
|
+
(laptop) or **📌** (pushpin), you're woken with a turn whose inbound is shaped
|
|
133
|
+
`<channel … event="reaction" emoji="👨💻" message_id="…" chat_id="…">[the
|
|
134
|
+
reacted message text]</channel>`. That reaction means: **"turn this into a
|
|
135
|
+
Linear issue."**
|
|
136
|
+
|
|
137
|
+
When you get such a reaction turn:
|
|
138
|
+
|
|
139
|
+
1. **Read the reacted message + nearby context.** The `[reacted text]` is the
|
|
140
|
+
seed. Pull the surrounding thread (`get_recent_messages`) when the ask needs
|
|
141
|
+
it — the issue should stand on its own without the operator re-explaining.
|
|
142
|
+
2. **Call `linear_create_issue`** with:
|
|
143
|
+
- `title` — a crisp, imperative one-liner ("Fix duplicate Brevo webhook
|
|
144
|
+
retries"), not a restatement of the chat.
|
|
145
|
+
- `body` — the ask, the context you gathered, and any acceptance criteria
|
|
146
|
+
you can reasonably infer. Markdown.
|
|
147
|
+
- `dedup_key` — set it to `"<chat_id>:<message_id>"` from the reaction event.
|
|
148
|
+
This makes a re-react of the same message idempotent (it returns the
|
|
149
|
+
existing issue instead of filing a duplicate).
|
|
150
|
+
- `team_id` — omit it. A single-team workspace auto-resolves; you'll only be
|
|
151
|
+
asked for one if the workspace has multiple teams (then tell the operator
|
|
152
|
+
to set a default via `switchroom linear-agent set-team`).
|
|
153
|
+
3. **Reply in plain text, not an emoji.** On success the tool returns
|
|
154
|
+
`Filed: <title> → <url>` — reply that link so the operator can click
|
|
155
|
+
through ("📋 Filed: <url>"). On failure (vault denial, multi-team, API
|
|
156
|
+
error) the tool returns actionable text — relay it plainly ("Couldn't file
|
|
157
|
+
it — …") and, if it's a vault denial, follow the `vault_request_access`
|
|
158
|
+
instruction it gives you, then retry.
|
|
159
|
+
|
|
160
|
+
Don't acknowledge with only a reaction or a bare "done" — the operator wants
|
|
161
|
+
the link (or the honest reason it didn't file).
|
|
162
|
+
{{/if}}
|
|
126
163
|
|
|
127
164
|
### Don't lie about scheduling
|
|
128
165
|
|
|
@@ -455,6 +455,61 @@ const TOOL_SCHEMAS = [
|
|
|
455
455
|
required: ['chat_id', 'key'],
|
|
456
456
|
},
|
|
457
457
|
},
|
|
458
|
+
{
|
|
459
|
+
name: 'linear_agent_activity',
|
|
460
|
+
description:
|
|
461
|
+
'Emit a structured Linear AgentActivity against an agent session (#2298). Use this ONLY inside a turn that was woken by a Linear agent session (the inbound carries meta.source="linear" and meta.agent_session_id) — pass that agent_session_id back here. Linear renders activities as status chips + a timeline on the issue, so the human sees acknowledge → work → result. Emit a `thought` within ~10s of being woken so the session does not look dead, then `message`(s) as you make progress, and finally exactly one terminal `complete` (work done) or `error` (you could not proceed). body is required for thought/message/error and optional for complete. Resolves the agent\'s Linear app token from the vault; on VAULT-BROKER-DENIED it returns an error instructing you to vault_request_access for `linear/<agent>/token`.',
|
|
462
|
+
inputSchema: {
|
|
463
|
+
type: 'object',
|
|
464
|
+
properties: {
|
|
465
|
+
agent_session_id: {
|
|
466
|
+
type: 'string',
|
|
467
|
+
description: 'The Linear AgentSession id — copy it verbatim from the woken turn\'s meta.agent_session_id.',
|
|
468
|
+
},
|
|
469
|
+
type: {
|
|
470
|
+
type: 'string',
|
|
471
|
+
enum: ['thought', 'message', 'complete', 'error'],
|
|
472
|
+
description: 'Activity kind. thought = visible reasoning ack (emit within ~10s); message = progress update; complete = terminal success; error = terminal failure.',
|
|
473
|
+
},
|
|
474
|
+
body: {
|
|
475
|
+
type: 'string',
|
|
476
|
+
description: 'Activity text (Markdown). Required for thought/message/error; optional for complete (a closing summary).',
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
required: ['agent_session_id', 'type'],
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: 'linear_create_issue',
|
|
484
|
+
description:
|
|
485
|
+
'File a new Linear issue from a Telegram message the operator flagged for capture (#2312). Use this when a turn was triggered by a capture reaction (the inbound carries event="reaction" with a capture emoji like 👨💻 or 📌) — turn the reacted message + any relevant thread context into a well-formed issue. Write a crisp imperative title and a body that captures the ask, the context, and any acceptance criteria you can infer; the agent files it AS its own Linear app actor. Team is auto-resolved when the workspace has a single team; if there are multiple it returns text asking for an explicit team_id. Pass dedup_key (e.g. the chat_id:message_id of the reacted message) so a re-react of the same message does not file a duplicate. Resolves the agent\'s Linear app token from the vault; on VAULT-BROKER-DENIED it returns text instructing you to vault_request_access for `linear/<agent>/token`. Returns "Filed: <title> → <url>" on success — reply that link to the operator in plain text.',
|
|
486
|
+
inputSchema: {
|
|
487
|
+
type: 'object',
|
|
488
|
+
properties: {
|
|
489
|
+
title: {
|
|
490
|
+
type: 'string',
|
|
491
|
+
description: 'Issue title — a crisp, imperative one-liner (e.g. "Fix duplicate webhook retries on Brevo sync").',
|
|
492
|
+
},
|
|
493
|
+
body: {
|
|
494
|
+
type: 'string',
|
|
495
|
+
description: 'Issue description (Markdown). Capture the ask, relevant context from the message/thread, and any acceptance criteria you can infer.',
|
|
496
|
+
},
|
|
497
|
+
team_id: {
|
|
498
|
+
type: 'string',
|
|
499
|
+
description: 'Optional Linear team id. Omit to auto-resolve when the workspace has a single team; required only when the workspace has multiple teams.',
|
|
500
|
+
},
|
|
501
|
+
dedup_key: {
|
|
502
|
+
type: 'string',
|
|
503
|
+
description: 'Optional idempotency key (use the reacted message identity, e.g. "<chat_id>:<message_id>"). A prior capture with the same key short-circuits to "Already filed: <url>".',
|
|
504
|
+
},
|
|
505
|
+
priority: {
|
|
506
|
+
type: 'number',
|
|
507
|
+
description: 'Optional Linear priority (0 none, 1 urgent, 2 high, 3 normal, 4 low).',
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
required: ['title', 'body'],
|
|
511
|
+
},
|
|
512
|
+
},
|
|
458
513
|
]
|
|
459
514
|
|
|
460
515
|
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_SCHEMAS }))
|
|
@@ -24934,6 +24934,59 @@ var TOOL_SCHEMAS = [
|
|
|
24934
24934
|
},
|
|
24935
24935
|
required: ["chat_id", "key"]
|
|
24936
24936
|
}
|
|
24937
|
+
},
|
|
24938
|
+
{
|
|
24939
|
+
name: "linear_agent_activity",
|
|
24940
|
+
description: 'Emit a structured Linear AgentActivity against an agent session (#2298). Use this ONLY inside a turn that was woken by a Linear agent session (the inbound carries meta.source="linear" and meta.agent_session_id) \u2014 pass that agent_session_id back here. Linear renders activities as status chips + a timeline on the issue, so the human sees acknowledge \u2192 work \u2192 result. Emit a `thought` within ~10s of being woken so the session does not look dead, then `message`(s) as you make progress, and finally exactly one terminal `complete` (work done) or `error` (you could not proceed). body is required for thought/message/error and optional for complete. Resolves the agent\'s Linear app token from the vault; on VAULT-BROKER-DENIED it returns an error instructing you to vault_request_access for `linear/<agent>/token`.',
|
|
24941
|
+
inputSchema: {
|
|
24942
|
+
type: "object",
|
|
24943
|
+
properties: {
|
|
24944
|
+
agent_session_id: {
|
|
24945
|
+
type: "string",
|
|
24946
|
+
description: "The Linear AgentSession id \u2014 copy it verbatim from the woken turn's meta.agent_session_id."
|
|
24947
|
+
},
|
|
24948
|
+
type: {
|
|
24949
|
+
type: "string",
|
|
24950
|
+
enum: ["thought", "message", "complete", "error"],
|
|
24951
|
+
description: "Activity kind. thought = visible reasoning ack (emit within ~10s); message = progress update; complete = terminal success; error = terminal failure."
|
|
24952
|
+
},
|
|
24953
|
+
body: {
|
|
24954
|
+
type: "string",
|
|
24955
|
+
description: "Activity text (Markdown). Required for thought/message/error; optional for complete (a closing summary)."
|
|
24956
|
+
}
|
|
24957
|
+
},
|
|
24958
|
+
required: ["agent_session_id", "type"]
|
|
24959
|
+
}
|
|
24960
|
+
},
|
|
24961
|
+
{
|
|
24962
|
+
name: "linear_create_issue",
|
|
24963
|
+
description: 'File a new Linear issue from a Telegram message the operator flagged for capture (#2312). Use this when a turn was triggered by a capture reaction (the inbound carries event="reaction" with a capture emoji like \uD83D\uDC68\u200D\uD83D\uDCBB or \uD83D\uDCCC) \u2014 turn the reacted message + any relevant thread context into a well-formed issue. Write a crisp imperative title and a body that captures the ask, the context, and any acceptance criteria you can infer; the agent files it AS its own Linear app actor. Team is auto-resolved when the workspace has a single team; if there are multiple it returns text asking for an explicit team_id. Pass dedup_key (e.g. the chat_id:message_id of the reacted message) so a re-react of the same message does not file a duplicate. Resolves the agent\'s Linear app token from the vault; on VAULT-BROKER-DENIED it returns text instructing you to vault_request_access for `linear/<agent>/token`. Returns "Filed: <title> \u2192 <url>" on success \u2014 reply that link to the operator in plain text.',
|
|
24964
|
+
inputSchema: {
|
|
24965
|
+
type: "object",
|
|
24966
|
+
properties: {
|
|
24967
|
+
title: {
|
|
24968
|
+
type: "string",
|
|
24969
|
+
description: 'Issue title \u2014 a crisp, imperative one-liner (e.g. "Fix duplicate webhook retries on Brevo sync").'
|
|
24970
|
+
},
|
|
24971
|
+
body: {
|
|
24972
|
+
type: "string",
|
|
24973
|
+
description: "Issue description (Markdown). Capture the ask, relevant context from the message/thread, and any acceptance criteria you can infer."
|
|
24974
|
+
},
|
|
24975
|
+
team_id: {
|
|
24976
|
+
type: "string",
|
|
24977
|
+
description: "Optional Linear team id. Omit to auto-resolve when the workspace has a single team; required only when the workspace has multiple teams."
|
|
24978
|
+
},
|
|
24979
|
+
dedup_key: {
|
|
24980
|
+
type: "string",
|
|
24981
|
+
description: 'Optional idempotency key (use the reacted message identity, e.g. "<chat_id>:<message_id>"). A prior capture with the same key short-circuits to "Already filed: <url>".'
|
|
24982
|
+
},
|
|
24983
|
+
priority: {
|
|
24984
|
+
type: "number",
|
|
24985
|
+
description: "Optional Linear priority (0 none, 1 urgent, 2 high, 3 normal, 4 low)."
|
|
24986
|
+
}
|
|
24987
|
+
},
|
|
24988
|
+
required: ["title", "body"]
|
|
24989
|
+
}
|
|
24937
24990
|
}
|
|
24938
24991
|
];
|
|
24939
24992
|
mcp.setRequestHandler(ListToolsRequestSchema2, async () => ({ tools: TOOL_SCHEMAS }));
|