switchroom 0.15.12 → 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 +12 -1
- package/dist/auth-broker/index.js +12 -1
- package/dist/cli/notion-write-pretool.mjs +12 -1
- package/dist/cli/switchroom.js +69 -8
- package/dist/host-control/main.js +12 -1
- package/dist/vault/approvals/kernel-server.js +12 -1
- package/dist/vault/broker/server.js +12 -1
- package/package.json +1 -1
- package/profiles/_shared/agent-self-service.md.hbs +37 -0
- package/telegram-plugin/bridge/bridge.ts +31 -0
- package/telegram-plugin/dist/bridge/bridge.js +30 -0
- package/telegram-plugin/dist/gateway/gateway.js +434 -50
- package/telegram-plugin/dist/server.js +30 -0
- package/telegram-plugin/gateway/gateway.ts +123 -6
- package/telegram-plugin/gateway/linear-activity.ts +145 -0
- package/telegram-plugin/scoped-approval.ts +253 -0
- package/telegram-plugin/tests/linear-agent-activity.test.ts +1 -1
- package/telegram-plugin/tests/linear-create-issue.test.ts +211 -0
- package/telegram-plugin/tests/permission-verdict-resume-guard.test.ts +13 -0
- package/telegram-plugin/tests/scoped-approval.test.ts +254 -0
|
@@ -11150,7 +11150,8 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
11150
11150
|
linear_agent: exports_external.object({
|
|
11151
11151
|
enabled: exports_external.boolean(),
|
|
11152
11152
|
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."),
|
|
11153
|
-
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.")
|
|
11153
|
+
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."),
|
|
11154
|
+
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>`.")
|
|
11154
11155
|
}).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."),
|
|
11155
11156
|
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."),
|
|
11156
11157
|
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`."),
|
|
@@ -12024,6 +12025,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
12024
12025
|
}
|
|
12025
12026
|
merged.reaction_dispatch = combined;
|
|
12026
12027
|
}
|
|
12028
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
12029
|
+
if (linearEnabled) {
|
|
12030
|
+
const rd = merged.reaction_dispatch;
|
|
12031
|
+
if (!rd || rd.emojis === undefined) {
|
|
12032
|
+
merged.reaction_dispatch = {
|
|
12033
|
+
enabled: rd?.enabled ?? true,
|
|
12034
|
+
emojis: ["\uD83D\uDC68\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
12035
|
+
};
|
|
12036
|
+
}
|
|
12037
|
+
}
|
|
12027
12038
|
if (defaults.resources || merged.resources) {
|
|
12028
12039
|
const d = defaults.resources ?? {};
|
|
12029
12040
|
const a = merged.resources ?? {};
|
|
@@ -11150,7 +11150,8 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
11150
11150
|
linear_agent: exports_external.object({
|
|
11151
11151
|
enabled: exports_external.boolean(),
|
|
11152
11152
|
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."),
|
|
11153
|
-
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.")
|
|
11153
|
+
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."),
|
|
11154
|
+
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>`.")
|
|
11154
11155
|
}).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."),
|
|
11155
11156
|
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."),
|
|
11156
11157
|
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`."),
|
|
@@ -12024,6 +12025,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
12024
12025
|
}
|
|
12025
12026
|
merged.reaction_dispatch = combined;
|
|
12026
12027
|
}
|
|
12028
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
12029
|
+
if (linearEnabled) {
|
|
12030
|
+
const rd = merged.reaction_dispatch;
|
|
12031
|
+
if (!rd || rd.emojis === undefined) {
|
|
12032
|
+
merged.reaction_dispatch = {
|
|
12033
|
+
enabled: rd?.enabled ?? true,
|
|
12034
|
+
emojis: ["\uD83D\uDC68\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
12035
|
+
};
|
|
12036
|
+
}
|
|
12037
|
+
}
|
|
12027
12038
|
if (defaults.resources || merged.resources) {
|
|
12028
12039
|
const d = defaults.resources ?? {};
|
|
12029
12040
|
const a = merged.resources ?? {};
|
|
@@ -11898,7 +11898,8 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
11898
11898
|
linear_agent: exports_external.object({
|
|
11899
11899
|
enabled: exports_external.boolean(),
|
|
11900
11900
|
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."),
|
|
11901
|
-
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational \u2014 used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace.")
|
|
11901
|
+
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational \u2014 used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace."),
|
|
11902
|
+
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>`.")
|
|
11902
11903
|
}).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 \u2014 opt in per agent. Cascades from " + "defaults.channels.telegram.linear_agent."),
|
|
11903
11904
|
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 \u2014 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."),
|
|
11904
11905
|
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 \u2014 set it only to pin a different " + "fallback topic. " + "Telegram's General topic is `id=1` at MTProto but sends omit the " + "field \u2014 the outbound wrapper strips `message_thread_id === 1` " + "on send. Forbidden when `dm_only: true`."),
|
|
@@ -12774,6 +12775,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
12774
12775
|
}
|
|
12775
12776
|
merged.reaction_dispatch = combined;
|
|
12776
12777
|
}
|
|
12778
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
12779
|
+
if (linearEnabled) {
|
|
12780
|
+
const rd = merged.reaction_dispatch;
|
|
12781
|
+
if (!rd || rd.emojis === undefined) {
|
|
12782
|
+
merged.reaction_dispatch = {
|
|
12783
|
+
enabled: rd?.enabled ?? true,
|
|
12784
|
+
emojis: ["\uD83D\uDC68\u200d\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
12785
|
+
};
|
|
12786
|
+
}
|
|
12787
|
+
}
|
|
12777
12788
|
if (defaults.resources || merged.resources) {
|
|
12778
12789
|
const d = defaults.resources ?? {};
|
|
12779
12790
|
const a = merged.resources ?? {};
|
package/dist/cli/switchroom.js
CHANGED
|
@@ -13714,7 +13714,8 @@ var init_schema = __esm(() => {
|
|
|
13714
13714
|
linear_agent: exports_external.object({
|
|
13715
13715
|
enabled: exports_external.boolean(),
|
|
13716
13716
|
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."),
|
|
13717
|
-
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational \u2014 used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace.")
|
|
13717
|
+
workspace_id: exports_external.string().optional().describe("Optional Linear workspace (organization) id this agent is " + "installed into. Informational \u2014 used for setup hints and " + "multi-workspace disambiguation; the token already scopes the " + "app to its workspace."),
|
|
13718
|
+
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>`.")
|
|
13718
13719
|
}).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 \u2014 opt in per agent. Cascades from " + "defaults.channels.telegram.linear_agent."),
|
|
13719
13720
|
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 \u2014 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."),
|
|
13720
13721
|
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 \u2014 set it only to pin a different " + "fallback topic. " + "Telegram's General topic is `id=1` at MTProto but sends omit the " + "field \u2014 the outbound wrapper strips `message_thread_id === 1` " + "on send. Forbidden when `dm_only: true`."),
|
|
@@ -14640,6 +14641,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
14640
14641
|
}
|
|
14641
14642
|
merged.reaction_dispatch = combined;
|
|
14642
14643
|
}
|
|
14644
|
+
const linearEnabled = merged.channels?.telegram?.linear_agent?.enabled === true;
|
|
14645
|
+
if (linearEnabled) {
|
|
14646
|
+
const rd = merged.reaction_dispatch;
|
|
14647
|
+
if (!rd || rd.emojis === undefined) {
|
|
14648
|
+
merged.reaction_dispatch = {
|
|
14649
|
+
enabled: rd?.enabled ?? true,
|
|
14650
|
+
emojis: ["\uD83D\uDC68\u200d\uD83D\uDCBB", "\uD83D\uDCCC"]
|
|
14651
|
+
};
|
|
14652
|
+
}
|
|
14653
|
+
}
|
|
14643
14654
|
if (defaults.resources || merged.resources) {
|
|
14644
14655
|
const d = defaults.resources ?? {};
|
|
14645
14656
|
const a = merged.resources ?? {};
|
|
@@ -50252,8 +50263,8 @@ var {
|
|
|
50252
50263
|
} = import__.default;
|
|
50253
50264
|
|
|
50254
50265
|
// src/build-info.ts
|
|
50255
|
-
var VERSION = "0.15.
|
|
50256
|
-
var COMMIT_SHA = "
|
|
50266
|
+
var VERSION = "0.15.13";
|
|
50267
|
+
var COMMIT_SHA = "36ba2682";
|
|
50257
50268
|
|
|
50258
50269
|
// src/cli/agent.ts
|
|
50259
50270
|
init_source();
|
|
@@ -51719,6 +51730,11 @@ function webkiteDenyForAgent(agentConfig) {
|
|
|
51719
51730
|
}
|
|
51720
51731
|
var SWITCHROOM_DEFAULT_MAIN_MODEL = "claude-sonnet-4-6";
|
|
51721
51732
|
var SWITCHROOM_DEFAULT_THINKING_EFFORT = "low";
|
|
51733
|
+
function resolveMainModel(model) {
|
|
51734
|
+
if (model === undefined || model === "default")
|
|
51735
|
+
return SWITCHROOM_DEFAULT_MAIN_MODEL;
|
|
51736
|
+
return model;
|
|
51737
|
+
}
|
|
51722
51738
|
function dedupe2(items) {
|
|
51723
51739
|
const seen = new Set;
|
|
51724
51740
|
const out = [];
|
|
@@ -51988,6 +52004,10 @@ function channelsToEnv(agent) {
|
|
|
51988
52004
|
if (tg.clear_status_on_completion !== undefined) {
|
|
51989
52005
|
out.SWITCHROOM_TG_CLEAR_STATUS_ON_COMPLETION = tg.clear_status_on_completion ? "1" : "0";
|
|
51990
52006
|
}
|
|
52007
|
+
const linearDefaultTeam = tg?.linear_agent?.default_team_id;
|
|
52008
|
+
if (linearDefaultTeam) {
|
|
52009
|
+
out.SWITCHROOM_LINEAR_DEFAULT_TEAM_ID = linearDefaultTeam;
|
|
52010
|
+
}
|
|
51991
52011
|
return out;
|
|
51992
52012
|
}
|
|
51993
52013
|
function buildRepoEnvVars(_agentName, agentDir, agent) {
|
|
@@ -52327,6 +52347,7 @@ function buildWorkspaceContext(args) {
|
|
|
52327
52347
|
useSwitchroomPlugin: usesSwitchroomTelegramPlugin(agentConfig),
|
|
52328
52348
|
useHotReloadStable: agentConfig.channels?.telegram?.hotReloadStable === true,
|
|
52329
52349
|
telegramEnabledFlag: agentConfig.channels?.telegram?.enabled === false ? "false" : "true",
|
|
52350
|
+
linearAgentEnabled: agentConfig.channels?.telegram?.linear_agent?.enabled === true,
|
|
52330
52351
|
securityPluginDir: DOCKER_SECURITY_PLUGIN_PATH,
|
|
52331
52352
|
hindsightEnabled: hindsightAutoRecallEnabled,
|
|
52332
52353
|
hindsightBankIdQ: shellSingleQuote(hindsightBankId),
|
|
@@ -52338,7 +52359,7 @@ function buildWorkspaceContext(args) {
|
|
|
52338
52359
|
hindsightTopicFilterMode,
|
|
52339
52360
|
switchroomConfigPathQ: switchroomConfigPath ? shellSingleQuote(resolve11(switchroomConfigPath)) : undefined,
|
|
52340
52361
|
hostHomeQ: process.env.HOME ? shellSingleQuote(process.env.HOME) : undefined,
|
|
52341
|
-
modelQ: shellSingleQuote(agentConfig.model
|
|
52362
|
+
modelQ: shellSingleQuote(resolveMainModel(agentConfig.model)),
|
|
52342
52363
|
...buildCronSessionContext(agentConfig),
|
|
52343
52364
|
thinkingEffort: agentConfig.thinking_effort ?? SWITCHROOM_DEFAULT_THINKING_EFFORT,
|
|
52344
52365
|
permissionMode: agentConfig.permission_mode,
|
|
@@ -52638,7 +52659,7 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
|
|
|
52638
52659
|
useSwitchroomPlugin: usesSwitchroomTelegramPlugin(agentConfig),
|
|
52639
52660
|
configPath: switchroomConfigPath
|
|
52640
52661
|
});
|
|
52641
|
-
settings.model = agentConfig.model
|
|
52662
|
+
settings.model = resolveMainModel(agentConfig.model);
|
|
52642
52663
|
const mergedSettings = agentConfig.settings_raw ? deepMergeJson(settings, agentConfig.settings_raw) : settings;
|
|
52643
52664
|
if (agentConfig.settings_raw && Object.keys(agentConfig.settings_raw).length > 0) {
|
|
52644
52665
|
mergedSettings._switchroomManagedRawKeys = Object.keys(agentConfig.settings_raw);
|
|
@@ -53429,7 +53450,7 @@ function reconcileAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchr
|
|
|
53429
53450
|
hindsightTopicAliasesJsonQ: hindsightTopicAliasesJson ? shellSingleQuote(hindsightTopicAliasesJson) : undefined,
|
|
53430
53451
|
hindsightTopicFilterMode,
|
|
53431
53452
|
hostHomeQ: process.env.HOME ? shellSingleQuote(process.env.HOME) : undefined,
|
|
53432
|
-
modelQ: shellSingleQuote(agentConfig.model
|
|
53453
|
+
modelQ: shellSingleQuote(resolveMainModel(agentConfig.model)),
|
|
53433
53454
|
...buildCronSessionContext(agentConfig),
|
|
53434
53455
|
thinkingEffort: agentConfig.thinking_effort ?? SWITCHROOM_DEFAULT_THINKING_EFFORT,
|
|
53435
53456
|
permissionMode: agentConfig.permission_mode,
|
|
@@ -53514,7 +53535,8 @@ function reconcileAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchr
|
|
|
53514
53535
|
schedule: agentConfig.schedule,
|
|
53515
53536
|
useSwitchroomPlugin: usesSwitchroomTelegramPlugin(agentConfig),
|
|
53516
53537
|
admin: agentConfig.admin === true || agentConfig.root === true,
|
|
53517
|
-
root: agentConfig.root === true
|
|
53538
|
+
root: agentConfig.root === true,
|
|
53539
|
+
linearAgentEnabled: agentConfig.channels?.telegram?.linear_agent?.enabled === true
|
|
53518
53540
|
};
|
|
53519
53541
|
let rendered = renderTemplate(claudeMdSrc, claudeContext);
|
|
53520
53542
|
const vaultProtocol = renderVaultProtocolFragment(claudeContext);
|
|
@@ -53680,7 +53702,7 @@ ${body}
|
|
|
53680
53702
|
}
|
|
53681
53703
|
}
|
|
53682
53704
|
}
|
|
53683
|
-
settings.model = agentConfig.model
|
|
53705
|
+
settings.model = resolveMainModel(agentConfig.model);
|
|
53684
53706
|
const mergedSettings = agentConfig.settings_raw ? deepMergeJson(settings, agentConfig.settings_raw) : settings;
|
|
53685
53707
|
if (agentConfig.settings_raw && Object.keys(agentConfig.settings_raw).length > 0) {
|
|
53686
53708
|
mergedSettings[META_KEY] = Object.keys(agentConfig.settings_raw);
|
|
@@ -67041,6 +67063,22 @@ function setLinearAgent(yamlText, agentName, opts) {
|
|
|
67041
67063
|
if (opts.workspaceId)
|
|
67042
67064
|
block.workspace_id = opts.workspaceId;
|
|
67043
67065
|
doc.setIn(["agents", agentName, "channels", "telegram", "linear_agent"], block);
|
|
67066
|
+
doc.setIn(["agents", agentName, "channels", "telegram", "webhook_via_gateway"], true);
|
|
67067
|
+
return String(doc);
|
|
67068
|
+
}
|
|
67069
|
+
function setLinearDefaultTeam(yamlText, agentName, teamId) {
|
|
67070
|
+
const doc = import_yaml11.parseDocument(yamlText);
|
|
67071
|
+
ensureAgent(doc, agentName);
|
|
67072
|
+
if (!doc.hasIn(["agents", agentName, "channels", "telegram", "linear_agent"])) {
|
|
67073
|
+
throw new Error(`agent '${agentName}' has no linear_agent block. Run 'switchroom linear-agent setup --agent ${agentName} --token <token>' first.`);
|
|
67074
|
+
}
|
|
67075
|
+
const path4 = ["agents", agentName, "channels", "telegram", "linear_agent", "default_team_id"];
|
|
67076
|
+
if (teamId === null) {
|
|
67077
|
+
if (doc.hasIn(path4))
|
|
67078
|
+
doc.deleteIn(path4);
|
|
67079
|
+
} else {
|
|
67080
|
+
doc.setIn(path4, teamId);
|
|
67081
|
+
}
|
|
67044
67082
|
return String(doc);
|
|
67045
67083
|
}
|
|
67046
67084
|
function setTelegramFeature(yamlText, agentName, feature, value) {
|
|
@@ -67642,6 +67680,29 @@ function registerLinearAgentCommand(program3) {
|
|
|
67642
67680
|
}
|
|
67643
67681
|
printLinearInstructions(opts, vaultKey);
|
|
67644
67682
|
}));
|
|
67683
|
+
linear.command("set-team").description("Set (or clear) the default Linear team captured issues file into for <agent>. Only needed when the workspace has multiple teams \u2014 a single-team workspace auto-resolves. Pass --clear to remove the default.").requiredOption("--agent <name>", "Agent name (must have a linear_agent block)").option("--team <id>", "Linear team id new captured issues default to.").option("--clear", "Remove the configured default team (revert to auto-resolve).").action(withConfigError(async (opts) => {
|
|
67684
|
+
if (!/^[a-z][a-z0-9_-]{0,63}$/.test(opts.agent)) {
|
|
67685
|
+
fail2(`--agent must be a lowercase agent slug (got '${opts.agent}').`);
|
|
67686
|
+
}
|
|
67687
|
+
if (!opts.clear && (!opts.team || opts.team.trim().length === 0)) {
|
|
67688
|
+
fail2("pass either --team <id> or --clear.");
|
|
67689
|
+
}
|
|
67690
|
+
const path4 = getConfigPath(program3);
|
|
67691
|
+
const before = readFileSync39(path4, "utf-8");
|
|
67692
|
+
let after;
|
|
67693
|
+
try {
|
|
67694
|
+
after = setLinearDefaultTeam(before, opts.agent, opts.clear ? null : opts.team.trim());
|
|
67695
|
+
} catch (err) {
|
|
67696
|
+
fail2(err.message);
|
|
67697
|
+
}
|
|
67698
|
+
writeFileSync22(path4, after, "utf-8");
|
|
67699
|
+
if (opts.clear) {
|
|
67700
|
+
console.log(source_default.green(`\u2713 Cleared default Linear team for '${opts.agent}' (auto-resolve).`));
|
|
67701
|
+
} else {
|
|
67702
|
+
console.log(source_default.green(`\u2713 Default Linear team for '${opts.agent}' set to ${opts.team.trim()}.`));
|
|
67703
|
+
}
|
|
67704
|
+
console.log(source_default.gray(` Run 'switchroom agent restart ${opts.agent}' to pick up the change.`));
|
|
67705
|
+
}));
|
|
67645
67706
|
}
|
|
67646
67707
|
function printLinearInstructions(opts, vaultKey) {
|
|
67647
67708
|
const base = opts.webhookBase ?? "https://<your-switchroom-web-host>";
|
|
@@ -13885,7 +13885,8 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
13885
13885
|
linear_agent: exports_external.object({
|
|
13886
13886
|
enabled: exports_external.boolean(),
|
|
13887
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.")
|
|
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>`.")
|
|
13889
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."),
|
|
13890
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."),
|
|
13891
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`."),
|
|
@@ -14769,6 +14770,16 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
14769
14770
|
}
|
|
14770
14771
|
merged.reaction_dispatch = combined;
|
|
14771
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
|
+
}
|
|
14772
14783
|
if (defaults.resources || merged.resources) {
|
|
14773
14784
|
const d = defaults.resources ?? {};
|
|
14774
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 ?? {};
|
|
@@ -11483,7 +11493,8 @@ var init_schema = __esm(() => {
|
|
|
11483
11493
|
linear_agent: exports_external.object({
|
|
11484
11494
|
enabled: exports_external.boolean(),
|
|
11485
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."),
|
|
11486
|
-
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.")
|
|
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>`.")
|
|
11487
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."),
|
|
11488
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."),
|
|
11489
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`."),
|
|
@@ -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 ?? {};
|
|
@@ -11483,7 +11493,8 @@ var init_schema = __esm(() => {
|
|
|
11483
11493
|
linear_agent: exports_external.object({
|
|
11484
11494
|
enabled: exports_external.boolean(),
|
|
11485
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."),
|
|
11486
|
-
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.")
|
|
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>`.")
|
|
11487
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."),
|
|
11488
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."),
|
|
11489
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`."),
|
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
|
|
|
@@ -479,6 +479,37 @@ const TOOL_SCHEMAS = [
|
|
|
479
479
|
required: ['agent_session_id', 'type'],
|
|
480
480
|
},
|
|
481
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
|
+
},
|
|
482
513
|
]
|
|
483
514
|
|
|
484
515
|
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_SCHEMAS }))
|
|
@@ -24957,6 +24957,36 @@ var TOOL_SCHEMAS = [
|
|
|
24957
24957
|
},
|
|
24958
24958
|
required: ["agent_session_id", "type"]
|
|
24959
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
|
+
}
|
|
24960
24990
|
}
|
|
24961
24991
|
];
|
|
24962
24992
|
mcp.setRequestHandler(ListToolsRequestSchema2, async () => ({ tools: TOOL_SCHEMAS }));
|