@vess-id/ai-identity 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8411 -21
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2103 -451
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2103 -451
- package/dist/index.mjs.map +1 -1
- package/dist/registry/__tests__/action-registry-freebusy.spec.d.ts +13 -0
- package/dist/registry/__tests__/action-registry-freebusy.spec.d.ts.map +1 -0
- package/dist/registry/__tests__/high-risk-resource-binding-invariant.spec.d.ts +30 -0
- package/dist/registry/__tests__/high-risk-resource-binding-invariant.spec.d.ts.map +1 -0
- package/dist/registry/action-registry-json.d.ts +8266 -25
- package/dist/registry/action-registry-json.d.ts.map +1 -1
- package/dist/registry/action-registry.d.ts.map +1 -1
- package/dist/registry/action-risk.d.ts +17 -1
- package/dist/registry/action-risk.d.ts.map +1 -1
- package/dist/registry/action-summary.d.ts +2 -0
- package/dist/registry/action-summary.d.ts.map +1 -1
- package/dist/types/connector-plugin.d.ts +15 -0
- package/dist/types/connector-plugin.d.ts.map +1 -1
- package/dist/types/permission-vc.d.ts +116 -0
- package/dist/types/permission-vc.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4006,7 +4006,7 @@ function validateRegistryObject(registry) {
|
|
|
4006
4006
|
for (const a of typed.actions) {
|
|
4007
4007
|
if (a.input_schema) {
|
|
4008
4008
|
try {
|
|
4009
|
-
const local = new Ajv({ strict: true, allErrors: true });
|
|
4009
|
+
const local = new Ajv({ strict: true, allErrors: true, allowUnionTypes: true });
|
|
4010
4010
|
addFormats(local);
|
|
4011
4011
|
const compiled = local.compile(a.input_schema);
|
|
4012
4012
|
if (compiled.errors?.length) {
|
|
@@ -6353,6 +6353,33 @@ var ACTION_REGISTRY = {
|
|
|
6353
6353
|
},
|
|
6354
6354
|
version: "1.0.0"
|
|
6355
6355
|
},
|
|
6356
|
+
{
|
|
6357
|
+
action: "calendar.freebusy",
|
|
6358
|
+
resource_type: "calendar:calendar",
|
|
6359
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
6360
|
+
required_scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
|
|
6361
|
+
capability: "calendar.read.basic",
|
|
6362
|
+
// Availability probe used to check a calendar's busy/free intervals before
|
|
6363
|
+
// proposing meeting slots. Returns only busy time ranges — never event
|
|
6364
|
+
// details (title, attendees, description) — so it stays low-risk read.
|
|
6365
|
+
input_schema: {
|
|
6366
|
+
type: "object",
|
|
6367
|
+
properties: {
|
|
6368
|
+
calendarId: { type: "string", description: "Calendar ID (email address). Defaults to primary calendar." },
|
|
6369
|
+
timeMin: { type: "string", description: 'Lower bound (inclusive) of the window to check, as ISO 8601 datetime, e.g. "2025-01-15T00:00:00Z"' },
|
|
6370
|
+
timeMax: { type: "string", description: 'Upper bound (exclusive) of the window to check, as ISO 8601 datetime, e.g. "2025-01-16T00:00:00Z"' }
|
|
6371
|
+
},
|
|
6372
|
+
required: ["timeMin", "timeMax"],
|
|
6373
|
+
additionalProperties: false
|
|
6374
|
+
},
|
|
6375
|
+
constraints: { rate_bucket: "calendar.read" },
|
|
6376
|
+
effects: ["Read:FreeBusy"],
|
|
6377
|
+
risk: "low",
|
|
6378
|
+
target_bindings: {
|
|
6379
|
+
resource_id: { source: "param", param: "calendarId", required: false, default: "primary" }
|
|
6380
|
+
},
|
|
6381
|
+
version: "1.0.0"
|
|
6382
|
+
},
|
|
6356
6383
|
{
|
|
6357
6384
|
action: "calendar.event.create",
|
|
6358
6385
|
resource_type: "calendar:event",
|
|
@@ -7545,449 +7572,1478 @@ var ACTION_REGISTRY = {
|
|
|
7545
7572
|
target_bindings: { resource_id: { source: "param", param: "portalId" } },
|
|
7546
7573
|
version: "1.0.0"
|
|
7547
7574
|
},
|
|
7548
|
-
// ───
|
|
7549
|
-
// Inbox actions back the Agent Inbox MCP tools (task delegation between
|
|
7550
|
-
// agents/people). They are internal (no external OAuth provider), so they
|
|
7551
|
-
// carry a single nominal base scope `inbox` to satisfy the registry
|
|
7552
|
-
// meta-schema's `minItems: 1` (same pattern as hubspot.account.link.get).
|
|
7575
|
+
// ─── Linear Actions ───
|
|
7553
7576
|
{
|
|
7554
|
-
action: "
|
|
7555
|
-
resource_type: "
|
|
7556
|
-
required_relations: ["editor", "
|
|
7557
|
-
required_scopes: ["
|
|
7558
|
-
capability: "
|
|
7577
|
+
action: "linear.issue.list",
|
|
7578
|
+
resource_type: "linear:issue",
|
|
7579
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7580
|
+
required_scopes: ["read"],
|
|
7581
|
+
capability: "linear.read.basic",
|
|
7559
7582
|
input_schema: {
|
|
7560
7583
|
type: "object",
|
|
7561
7584
|
properties: {
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7585
|
+
teamId: { type: "string", description: "Filter by team ID" },
|
|
7586
|
+
assigneeId: { type: "string", description: "Filter by assignee user ID" },
|
|
7587
|
+
assigneeMe: { type: "boolean", description: "If true, filter issues assigned to the authenticated user" },
|
|
7588
|
+
stateId: { type: "string", description: "Filter by workflow state ID" },
|
|
7589
|
+
priority: { type: "number", minimum: 0, maximum: 4, description: "0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low" },
|
|
7590
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of issues to return (default 50)" }
|
|
7566
7591
|
},
|
|
7567
|
-
required: ["to", "taskType", "payload"],
|
|
7568
7592
|
additionalProperties: false
|
|
7569
7593
|
},
|
|
7570
|
-
constraints: { rate_bucket: "
|
|
7571
|
-
effects: ["
|
|
7572
|
-
risk: "
|
|
7594
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7595
|
+
effects: ["Read:IssueList"],
|
|
7596
|
+
risk: "low",
|
|
7573
7597
|
target_bindings: {
|
|
7574
|
-
resource_id: { source: "param", param: "
|
|
7598
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7575
7599
|
},
|
|
7576
7600
|
version: "1.0.0"
|
|
7577
7601
|
},
|
|
7578
7602
|
{
|
|
7579
|
-
action: "
|
|
7580
|
-
resource_type: "
|
|
7581
|
-
required_relations: ["editor", "
|
|
7582
|
-
required_scopes: ["
|
|
7583
|
-
capability: "
|
|
7603
|
+
action: "linear.issue.read",
|
|
7604
|
+
resource_type: "linear:issue",
|
|
7605
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7606
|
+
required_scopes: ["read"],
|
|
7607
|
+
capability: "linear.read.basic",
|
|
7584
7608
|
input_schema: {
|
|
7585
7609
|
type: "object",
|
|
7586
7610
|
properties: {
|
|
7587
|
-
|
|
7588
|
-
action: { type: "string", enum: ["accept", "decline", "counter"], description: "Response action" },
|
|
7589
|
-
data: { type: "object", description: "Optional response data (e.g. counter-proposal)" }
|
|
7611
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier (e.g. ENG-123)" }
|
|
7590
7612
|
},
|
|
7591
|
-
required: ["
|
|
7613
|
+
required: ["issueId"],
|
|
7592
7614
|
additionalProperties: false
|
|
7593
7615
|
},
|
|
7594
|
-
constraints: { rate_bucket: "
|
|
7595
|
-
effects: ["
|
|
7596
|
-
|
|
7597
|
-
// go through human approval — the Phase 1 "always confirm" guarantee made
|
|
7598
|
-
// enforceable. target_bindings below binds the concrete inbox item id so
|
|
7599
|
-
// the high-risk approval has a specific resource constraint (the public
|
|
7600
|
-
// /scheduling/:token link flow does NOT go through this gate — it calls
|
|
7601
|
-
// InboxService.respond directly, system-key-signed).
|
|
7602
|
-
risk: "high",
|
|
7616
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7617
|
+
effects: ["Read:Issue"],
|
|
7618
|
+
risk: "low",
|
|
7603
7619
|
target_bindings: {
|
|
7604
|
-
resource_id: { source: "param", param: "
|
|
7620
|
+
resource_id: { source: "param", param: "issueId" }
|
|
7605
7621
|
},
|
|
7606
7622
|
version: "1.0.0"
|
|
7607
7623
|
},
|
|
7608
7624
|
{
|
|
7609
|
-
action: "
|
|
7610
|
-
resource_type: "
|
|
7625
|
+
action: "linear.issue.search",
|
|
7626
|
+
resource_type: "linear:issue",
|
|
7611
7627
|
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7612
|
-
required_scopes: ["
|
|
7613
|
-
capability: "
|
|
7628
|
+
required_scopes: ["read"],
|
|
7629
|
+
capability: "linear.read.basic",
|
|
7614
7630
|
input_schema: {
|
|
7615
7631
|
type: "object",
|
|
7616
7632
|
properties: {
|
|
7617
|
-
|
|
7618
|
-
|
|
7633
|
+
query: { type: "string", minLength: 1, description: "Full-text search query" },
|
|
7634
|
+
teamId: { type: "string", description: "Restrict search to a specific team" },
|
|
7635
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of results (default 50)" }
|
|
7619
7636
|
},
|
|
7637
|
+
required: ["query"],
|
|
7620
7638
|
additionalProperties: false
|
|
7621
7639
|
},
|
|
7622
|
-
constraints: { rate_bucket: "
|
|
7623
|
-
effects: ["Read:
|
|
7640
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7641
|
+
effects: ["Read:IssueList"],
|
|
7624
7642
|
risk: "low",
|
|
7625
7643
|
target_bindings: {
|
|
7626
|
-
resource_id: { source: "param", param: "
|
|
7644
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7627
7645
|
},
|
|
7628
7646
|
version: "1.0.0"
|
|
7629
7647
|
},
|
|
7630
7648
|
{
|
|
7631
|
-
action: "
|
|
7632
|
-
resource_type: "
|
|
7633
|
-
required_relations: ["
|
|
7634
|
-
required_scopes: ["
|
|
7635
|
-
capability: "
|
|
7649
|
+
action: "linear.issue.create",
|
|
7650
|
+
resource_type: "linear:issue",
|
|
7651
|
+
required_relations: ["editor", "act_as"],
|
|
7652
|
+
required_scopes: ["issues:create"],
|
|
7653
|
+
capability: "linear.write.basic",
|
|
7636
7654
|
input_schema: {
|
|
7637
7655
|
type: "object",
|
|
7638
7656
|
properties: {
|
|
7639
|
-
|
|
7657
|
+
teamId: { type: "string", minLength: 1, description: "Team ID to create the issue in" },
|
|
7658
|
+
title: { type: "string", minLength: 1, description: "Issue title" },
|
|
7659
|
+
description: { type: "string", description: "Issue description (Markdown)" },
|
|
7660
|
+
assigneeId: { type: "string", description: "Assignee user ID" },
|
|
7661
|
+
stateId: { type: "string", description: "Workflow state ID" },
|
|
7662
|
+
priority: { type: "number", minimum: 0, maximum: 4, description: "0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low" },
|
|
7663
|
+
labelIds: { type: "array", items: { type: "string" }, description: "Label IDs to attach" }
|
|
7640
7664
|
},
|
|
7641
|
-
required: ["
|
|
7665
|
+
required: ["teamId", "title"],
|
|
7642
7666
|
additionalProperties: false
|
|
7643
7667
|
},
|
|
7644
|
-
constraints: { rate_bucket: "
|
|
7645
|
-
effects: ["
|
|
7646
|
-
risk: "
|
|
7668
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7669
|
+
effects: ["Create:Issue"],
|
|
7670
|
+
risk: "high",
|
|
7647
7671
|
target_bindings: {
|
|
7648
|
-
resource_id: { source: "param", param: "
|
|
7672
|
+
resource_id: { source: "param", param: "teamId" }
|
|
7649
7673
|
},
|
|
7650
7674
|
version: "1.0.0"
|
|
7651
7675
|
},
|
|
7652
7676
|
{
|
|
7653
|
-
action: "
|
|
7654
|
-
resource_type: "
|
|
7677
|
+
action: "linear.issue.update",
|
|
7678
|
+
resource_type: "linear:issue",
|
|
7655
7679
|
required_relations: ["editor", "act_as"],
|
|
7656
|
-
required_scopes: ["
|
|
7657
|
-
capability: "
|
|
7680
|
+
required_scopes: ["write"],
|
|
7681
|
+
capability: "linear.write.basic",
|
|
7658
7682
|
input_schema: {
|
|
7659
7683
|
type: "object",
|
|
7660
7684
|
properties: {
|
|
7661
|
-
|
|
7662
|
-
|
|
7685
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier (e.g. ENG-123)" },
|
|
7686
|
+
title: { type: "string", description: "New title" },
|
|
7687
|
+
description: { type: "string", description: "New description (Markdown)" },
|
|
7688
|
+
assigneeId: { type: "string", description: "Assignee user ID (null to unassign)" },
|
|
7689
|
+
stateId: { type: "string", description: "Workflow state ID" },
|
|
7690
|
+
priority: { type: "number", minimum: 0, maximum: 4, description: "0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low" },
|
|
7691
|
+
labelIds: { type: "array", items: { type: "string" }, description: "New set of label IDs" }
|
|
7663
7692
|
},
|
|
7664
|
-
required: ["
|
|
7693
|
+
required: ["issueId"],
|
|
7665
7694
|
additionalProperties: false
|
|
7666
7695
|
},
|
|
7667
|
-
constraints: { rate_bucket: "
|
|
7668
|
-
effects: ["Update:
|
|
7669
|
-
risk: "
|
|
7696
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7697
|
+
effects: ["Update:Issue"],
|
|
7698
|
+
risk: "high",
|
|
7670
7699
|
target_bindings: {
|
|
7671
|
-
resource_id: { source: "param", param: "
|
|
7700
|
+
resource_id: { source: "param", param: "issueId" }
|
|
7672
7701
|
},
|
|
7673
7702
|
version: "1.0.0"
|
|
7674
7703
|
},
|
|
7675
|
-
// ─── Scheduling Actions (internal) ───
|
|
7676
|
-
// scheduling.request is a meeting-time negotiation façade over inbox.send.
|
|
7677
|
-
// Candidate slots are computed LLM-side from the user calendar; the server
|
|
7678
|
-
// only validates them. Like the inbox actions it is internal (no external
|
|
7679
|
-
// OAuth provider), so it carries the single nominal base scope `inbox`.
|
|
7680
|
-
// Spec: docs/specs/2026-06-10-inbox-intent-routing-design.md §2.1
|
|
7681
7704
|
{
|
|
7682
|
-
action: "
|
|
7683
|
-
resource_type: "
|
|
7705
|
+
action: "linear.comment.create",
|
|
7706
|
+
resource_type: "linear:comment",
|
|
7684
7707
|
required_relations: ["editor", "act_as"],
|
|
7685
|
-
required_scopes: ["
|
|
7686
|
-
capability: "
|
|
7708
|
+
required_scopes: ["comments:create"],
|
|
7709
|
+
capability: "linear.write.basic",
|
|
7687
7710
|
input_schema: {
|
|
7688
7711
|
type: "object",
|
|
7689
7712
|
properties: {
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
durationMinutes: { type: "integer", minimum: 5, maximum: 480, description: "Meeting length in minutes" },
|
|
7693
|
-
candidates: {
|
|
7694
|
-
type: "array",
|
|
7695
|
-
minItems: 1,
|
|
7696
|
-
maxItems: 10,
|
|
7697
|
-
description: "Candidate slots computed by the agent from the user calendar (LLM-side computation; the server only validates)",
|
|
7698
|
-
items: {
|
|
7699
|
-
type: "object",
|
|
7700
|
-
properties: {
|
|
7701
|
-
start: { type: "string", description: "ISO 8601 start" },
|
|
7702
|
-
end: { type: "string", description: "ISO 8601 end" }
|
|
7703
|
-
},
|
|
7704
|
-
required: ["start", "end"],
|
|
7705
|
-
additionalProperties: false
|
|
7706
|
-
}
|
|
7707
|
-
},
|
|
7708
|
-
message: { type: "string", description: "Optional human-readable message" }
|
|
7713
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to comment on" },
|
|
7714
|
+
body: { type: "string", minLength: 1, description: "Comment body (Markdown)" }
|
|
7709
7715
|
},
|
|
7710
|
-
required: ["
|
|
7716
|
+
required: ["issueId", "body"],
|
|
7711
7717
|
additionalProperties: false
|
|
7712
7718
|
},
|
|
7713
|
-
constraints: { rate_bucket: "
|
|
7714
|
-
effects: ["Create:
|
|
7719
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7720
|
+
effects: ["Create:Comment"],
|
|
7715
7721
|
risk: "high",
|
|
7716
7722
|
target_bindings: {
|
|
7717
|
-
resource_id: { source: "param", param: "
|
|
7723
|
+
resource_id: { source: "param", param: "issueId" }
|
|
7718
7724
|
},
|
|
7719
7725
|
version: "1.0.0"
|
|
7720
|
-
}
|
|
7721
|
-
],
|
|
7722
|
-
capabilities: [
|
|
7723
|
-
{
|
|
7724
|
-
capability: "slack.messaging.basic",
|
|
7725
|
-
description: "Post, update, and delete messages in channels",
|
|
7726
|
-
includes: ["slack.message.post", "slack.message.update", "slack.message.delete"],
|
|
7727
|
-
version: "1.0.0"
|
|
7728
7726
|
},
|
|
7729
7727
|
{
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7728
|
+
action: "linear.comment.list",
|
|
7729
|
+
resource_type: "linear:comment",
|
|
7730
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7731
|
+
required_scopes: ["read"],
|
|
7732
|
+
capability: "linear.read.basic",
|
|
7733
|
+
input_schema: {
|
|
7734
|
+
type: "object",
|
|
7735
|
+
properties: {
|
|
7736
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to list comments for" },
|
|
7737
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of comments (default 50)" }
|
|
7738
|
+
},
|
|
7739
|
+
required: ["issueId"],
|
|
7740
|
+
additionalProperties: false
|
|
7741
|
+
},
|
|
7742
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7743
|
+
effects: ["Read:CommentList"],
|
|
7744
|
+
risk: "low",
|
|
7745
|
+
target_bindings: {
|
|
7746
|
+
resource_id: { source: "param", param: "issueId" }
|
|
7747
|
+
},
|
|
7733
7748
|
version: "1.0.0"
|
|
7734
7749
|
},
|
|
7735
7750
|
{
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7751
|
+
action: "linear.project.list",
|
|
7752
|
+
resource_type: "linear:project",
|
|
7753
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7754
|
+
required_scopes: ["read"],
|
|
7755
|
+
capability: "linear.read.basic",
|
|
7756
|
+
input_schema: {
|
|
7757
|
+
type: "object",
|
|
7758
|
+
properties: {
|
|
7759
|
+
teamId: { type: "string", description: "Filter by team ID" },
|
|
7760
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of projects (default 50)" }
|
|
7761
|
+
},
|
|
7762
|
+
additionalProperties: false
|
|
7763
|
+
},
|
|
7764
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7765
|
+
effects: ["Read:ProjectList"],
|
|
7766
|
+
risk: "low",
|
|
7767
|
+
target_bindings: {
|
|
7768
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7769
|
+
},
|
|
7739
7770
|
version: "1.0.0"
|
|
7740
7771
|
},
|
|
7741
7772
|
{
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7773
|
+
action: "linear.project.read",
|
|
7774
|
+
resource_type: "linear:project",
|
|
7775
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7776
|
+
required_scopes: ["read"],
|
|
7777
|
+
capability: "linear.read.basic",
|
|
7778
|
+
input_schema: {
|
|
7779
|
+
type: "object",
|
|
7780
|
+
properties: {
|
|
7781
|
+
projectId: { type: "string", minLength: 1, description: "Project ID" }
|
|
7782
|
+
},
|
|
7783
|
+
required: ["projectId"],
|
|
7784
|
+
additionalProperties: false
|
|
7785
|
+
},
|
|
7786
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7787
|
+
effects: ["Read:Project"],
|
|
7788
|
+
risk: "low",
|
|
7789
|
+
target_bindings: {
|
|
7790
|
+
resource_id: { source: "param", param: "projectId" }
|
|
7791
|
+
},
|
|
7745
7792
|
version: "1.0.0"
|
|
7746
7793
|
},
|
|
7747
7794
|
{
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7795
|
+
action: "linear.team.list",
|
|
7796
|
+
resource_type: "linear:team",
|
|
7797
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7798
|
+
required_scopes: ["read"],
|
|
7799
|
+
capability: "linear.read.basic",
|
|
7800
|
+
input_schema: {
|
|
7801
|
+
type: "object",
|
|
7802
|
+
properties: {
|
|
7803
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of teams (default 50)" }
|
|
7804
|
+
},
|
|
7805
|
+
additionalProperties: false
|
|
7806
|
+
},
|
|
7807
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7808
|
+
effects: ["Read:TeamList"],
|
|
7809
|
+
risk: "low",
|
|
7810
|
+
// No teamId parameter: this action lists ALL accessible teams — intentionally
|
|
7811
|
+
// not scoped to a single team. required:false signals that missing resource
|
|
7812
|
+
// binding is expected (not an omission), consistent with slack.channel.read.
|
|
7813
|
+
target_bindings: {
|
|
7814
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7815
|
+
},
|
|
7751
7816
|
version: "1.0.0"
|
|
7752
7817
|
},
|
|
7753
7818
|
{
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7819
|
+
action: "linear.workflowState.list",
|
|
7820
|
+
resource_type: "linear:workflowState",
|
|
7821
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7822
|
+
required_scopes: ["read"],
|
|
7823
|
+
capability: "linear.read.basic",
|
|
7824
|
+
input_schema: {
|
|
7825
|
+
type: "object",
|
|
7826
|
+
properties: {
|
|
7827
|
+
teamId: { type: "string", description: "Filter by team ID" },
|
|
7828
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of workflow states to return (default 50)" }
|
|
7829
|
+
},
|
|
7830
|
+
additionalProperties: false
|
|
7831
|
+
},
|
|
7832
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7833
|
+
effects: ["Read:WorkflowStateList"],
|
|
7834
|
+
risk: "low",
|
|
7835
|
+
target_bindings: {
|
|
7836
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7837
|
+
},
|
|
7757
7838
|
version: "1.0.0"
|
|
7758
7839
|
},
|
|
7759
7840
|
{
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7841
|
+
action: "linear.viewer.read",
|
|
7842
|
+
resource_type: "linear:viewer",
|
|
7843
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7844
|
+
required_scopes: ["read"],
|
|
7845
|
+
capability: "linear.read.basic",
|
|
7846
|
+
input_schema: {
|
|
7847
|
+
type: "object",
|
|
7848
|
+
properties: {},
|
|
7849
|
+
additionalProperties: false
|
|
7850
|
+
},
|
|
7851
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7852
|
+
effects: ["Read:Viewer"],
|
|
7853
|
+
risk: "low",
|
|
7854
|
+
// No parameters: this action reads the currently authenticated user — there is
|
|
7855
|
+
// no resource to scope to. required:false signals intentional exemption, not
|
|
7856
|
+
// omission, consistent with the slack.channel.read precedent.
|
|
7857
|
+
target_bindings: {
|
|
7858
|
+
resource_id: { source: "param", param: "viewerId", required: false }
|
|
7859
|
+
},
|
|
7763
7860
|
version: "1.0.0"
|
|
7764
7861
|
},
|
|
7765
7862
|
{
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7863
|
+
action: "linear.label.list",
|
|
7864
|
+
resource_type: "linear:label",
|
|
7865
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7866
|
+
required_scopes: ["read"],
|
|
7867
|
+
capability: "linear.read.basic",
|
|
7868
|
+
input_schema: {
|
|
7869
|
+
type: "object",
|
|
7870
|
+
properties: {
|
|
7871
|
+
teamId: { type: "string", description: "Filter labels by team ID" },
|
|
7872
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of labels to return (default 50)" }
|
|
7873
|
+
},
|
|
7874
|
+
additionalProperties: false
|
|
7875
|
+
},
|
|
7876
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7877
|
+
effects: ["Read:LabelList"],
|
|
7878
|
+
risk: "low",
|
|
7879
|
+
target_bindings: {
|
|
7880
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7881
|
+
},
|
|
7769
7882
|
version: "1.0.0"
|
|
7770
7883
|
},
|
|
7771
7884
|
{
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7885
|
+
action: "linear.user.list",
|
|
7886
|
+
resource_type: "linear:team",
|
|
7887
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
7888
|
+
required_scopes: ["read"],
|
|
7889
|
+
capability: "linear.read.basic",
|
|
7890
|
+
input_schema: {
|
|
7891
|
+
type: "object",
|
|
7892
|
+
properties: {
|
|
7893
|
+
teamId: { type: "string", description: "Filter by team ID (lists team members only)" },
|
|
7894
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of users to return (default 50)" }
|
|
7895
|
+
},
|
|
7896
|
+
additionalProperties: false
|
|
7897
|
+
},
|
|
7898
|
+
constraints: { rate_bucket: "linear.read" },
|
|
7899
|
+
effects: ["Read:UserList"],
|
|
7900
|
+
risk: "low",
|
|
7901
|
+
target_bindings: {
|
|
7902
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
7903
|
+
},
|
|
7775
7904
|
version: "1.0.0"
|
|
7776
7905
|
},
|
|
7777
7906
|
{
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7907
|
+
action: "linear.issue.archive",
|
|
7908
|
+
resource_type: "linear:issue",
|
|
7909
|
+
required_relations: ["editor", "act_as"],
|
|
7910
|
+
required_scopes: ["write"],
|
|
7911
|
+
capability: "linear.write.basic",
|
|
7912
|
+
input_schema: {
|
|
7913
|
+
type: "object",
|
|
7914
|
+
properties: {
|
|
7915
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier to archive (e.g. ENG-123)" }
|
|
7916
|
+
},
|
|
7917
|
+
required: ["issueId"],
|
|
7918
|
+
additionalProperties: false
|
|
7919
|
+
},
|
|
7920
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7921
|
+
effects: ["Archive:Issue"],
|
|
7922
|
+
risk: "high",
|
|
7923
|
+
target_bindings: {
|
|
7924
|
+
resource_id: { source: "param", param: "issueId" }
|
|
7925
|
+
},
|
|
7781
7926
|
version: "1.0.0"
|
|
7782
7927
|
},
|
|
7783
7928
|
{
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7929
|
+
action: "linear.project.create",
|
|
7930
|
+
resource_type: "linear:project",
|
|
7931
|
+
required_relations: ["editor", "act_as"],
|
|
7932
|
+
required_scopes: ["write"],
|
|
7933
|
+
capability: "linear.write.basic",
|
|
7934
|
+
input_schema: {
|
|
7935
|
+
type: "object",
|
|
7936
|
+
properties: {
|
|
7937
|
+
name: { type: "string", minLength: 1, description: "Project name" },
|
|
7938
|
+
teamIds: { type: "array", items: { type: "string" }, minItems: 1, description: "Team IDs to associate with the project (at least one required)" },
|
|
7939
|
+
teamId: { type: "string", description: "Primary team ID (first element of teamIds; used for authorization scope)" },
|
|
7940
|
+
description: { type: "string", description: "Project description (Markdown)" },
|
|
7941
|
+
statusId: { type: "string", description: "Project status ID. Note: this is a ProjectStatus ID, not a WorkflowState ID. ProjectStatus can be retrieved via the Linear API projectStatuses query." },
|
|
7942
|
+
startDate: { type: "string", description: "Start date (ISO 8601, e.g. 2024-01-01)" },
|
|
7943
|
+
targetDate: { type: "string", description: "Target completion date (ISO 8601)" }
|
|
7944
|
+
},
|
|
7945
|
+
required: ["name", "teamIds"],
|
|
7946
|
+
additionalProperties: false
|
|
7947
|
+
},
|
|
7948
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7949
|
+
effects: ["Create:Project"],
|
|
7950
|
+
risk: "high",
|
|
7951
|
+
target_bindings: {
|
|
7952
|
+
// teamId はスキーマの scalar フィールド (teamIds[0] の alias)。
|
|
7953
|
+
// teamId が明示指定されている場合はそれを使い、未指定の場合は
|
|
7954
|
+
// fallback_param: 'teamIds' で teamIds[0] にフォールバック(resolver は
|
|
7955
|
+
// 配列の first element を自動的にスカラーに変換する)。
|
|
7956
|
+
// extractResources も同じ優先順位 (teamId → teamIds[0]) で解決するため
|
|
7957
|
+
// 両者のバインドが常に一致する。required:true で高リスク CREATE の
|
|
7958
|
+
// resource binding 必須契約を明示 (teamIds は minItems:1 なので常に解決する)。
|
|
7959
|
+
resource_id: { source: "param", param: "teamId", fallback_param: "teamIds", required: true }
|
|
7960
|
+
},
|
|
7787
7961
|
version: "1.0.0"
|
|
7788
7962
|
},
|
|
7789
7963
|
{
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7964
|
+
action: "linear.project.update",
|
|
7965
|
+
resource_type: "linear:project",
|
|
7966
|
+
required_relations: ["editor", "act_as"],
|
|
7967
|
+
required_scopes: ["write"],
|
|
7968
|
+
capability: "linear.write.basic",
|
|
7969
|
+
input_schema: {
|
|
7970
|
+
type: "object",
|
|
7971
|
+
properties: {
|
|
7972
|
+
projectId: { type: "string", minLength: 1, description: "Project ID to update" },
|
|
7973
|
+
name: { type: "string", description: "New project name" },
|
|
7974
|
+
description: { type: "string", description: "New project description (Markdown)" },
|
|
7975
|
+
statusId: { type: "string", description: "New project status ID. Note: this is a ProjectStatus ID, not a WorkflowState ID." },
|
|
7976
|
+
startDate: { type: "string", description: "New start date (ISO 8601)" },
|
|
7977
|
+
targetDate: { type: "string", description: "New target date (ISO 8601)" }
|
|
7978
|
+
},
|
|
7979
|
+
required: ["projectId"],
|
|
7980
|
+
additionalProperties: false
|
|
7981
|
+
},
|
|
7982
|
+
constraints: { rate_bucket: "linear.write" },
|
|
7983
|
+
effects: ["Update:Project"],
|
|
7984
|
+
risk: "high",
|
|
7985
|
+
target_bindings: {
|
|
7986
|
+
resource_id: { source: "param", param: "projectId" }
|
|
7987
|
+
},
|
|
7793
7988
|
version: "1.0.0"
|
|
7794
7989
|
},
|
|
7990
|
+
// ─── Linear Comment ops ───
|
|
7795
7991
|
{
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7992
|
+
action: "linear.comment.update",
|
|
7993
|
+
resource_type: "linear:comment",
|
|
7994
|
+
required_relations: ["editor", "act_as"],
|
|
7995
|
+
required_scopes: ["comments:create"],
|
|
7996
|
+
capability: "linear.write.basic",
|
|
7997
|
+
input_schema: {
|
|
7998
|
+
type: "object",
|
|
7999
|
+
properties: {
|
|
8000
|
+
commentId: { type: "string", minLength: 1, description: "Comment ID to update" },
|
|
8001
|
+
body: { type: "string", minLength: 1, description: "New comment body (Markdown)" }
|
|
8002
|
+
},
|
|
8003
|
+
required: ["commentId", "body"],
|
|
8004
|
+
additionalProperties: false
|
|
8005
|
+
},
|
|
8006
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8007
|
+
effects: ["Update:Comment"],
|
|
8008
|
+
risk: "high",
|
|
8009
|
+
target_bindings: {
|
|
8010
|
+
resource_id: { source: "param", param: "commentId" }
|
|
8011
|
+
},
|
|
7799
8012
|
version: "1.0.0"
|
|
7800
8013
|
},
|
|
7801
8014
|
{
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
8015
|
+
action: "linear.comment.delete",
|
|
8016
|
+
resource_type: "linear:comment",
|
|
8017
|
+
required_relations: ["editor", "act_as"],
|
|
8018
|
+
required_scopes: ["write"],
|
|
8019
|
+
capability: "linear.write.basic",
|
|
8020
|
+
input_schema: {
|
|
8021
|
+
type: "object",
|
|
8022
|
+
properties: {
|
|
8023
|
+
commentId: { type: "string", minLength: 1, description: "Comment ID to delete" }
|
|
8024
|
+
},
|
|
8025
|
+
required: ["commentId"],
|
|
8026
|
+
additionalProperties: false
|
|
8027
|
+
},
|
|
8028
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8029
|
+
effects: ["Delete:Comment"],
|
|
8030
|
+
risk: "high",
|
|
8031
|
+
target_bindings: {
|
|
8032
|
+
resource_id: { source: "param", param: "commentId" }
|
|
8033
|
+
},
|
|
7805
8034
|
version: "1.0.0"
|
|
7806
8035
|
},
|
|
7807
8036
|
{
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
8037
|
+
action: "linear.comment.resolve",
|
|
8038
|
+
resource_type: "linear:comment",
|
|
8039
|
+
required_relations: ["editor", "act_as"],
|
|
8040
|
+
required_scopes: ["write"],
|
|
8041
|
+
capability: "linear.write.basic",
|
|
8042
|
+
input_schema: {
|
|
8043
|
+
type: "object",
|
|
8044
|
+
properties: {
|
|
8045
|
+
commentId: { type: "string", minLength: 1, description: "Comment ID to resolve" }
|
|
8046
|
+
},
|
|
8047
|
+
required: ["commentId"],
|
|
8048
|
+
additionalProperties: false
|
|
8049
|
+
},
|
|
8050
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8051
|
+
effects: ["Update:Comment"],
|
|
8052
|
+
risk: "high",
|
|
8053
|
+
target_bindings: {
|
|
8054
|
+
resource_id: { source: "param", param: "commentId" }
|
|
8055
|
+
},
|
|
7811
8056
|
version: "1.0.0"
|
|
7812
8057
|
},
|
|
7813
8058
|
{
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
8059
|
+
action: "linear.comment.unresolve",
|
|
8060
|
+
resource_type: "linear:comment",
|
|
8061
|
+
required_relations: ["editor", "act_as"],
|
|
8062
|
+
required_scopes: ["write"],
|
|
8063
|
+
capability: "linear.write.basic",
|
|
8064
|
+
input_schema: {
|
|
8065
|
+
type: "object",
|
|
8066
|
+
properties: {
|
|
8067
|
+
commentId: { type: "string", minLength: 1, description: "Comment ID to unresolve" }
|
|
8068
|
+
},
|
|
8069
|
+
required: ["commentId"],
|
|
8070
|
+
additionalProperties: false
|
|
8071
|
+
},
|
|
8072
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8073
|
+
effects: ["Update:Comment"],
|
|
8074
|
+
risk: "high",
|
|
8075
|
+
target_bindings: {
|
|
8076
|
+
resource_id: { source: "param", param: "commentId" }
|
|
8077
|
+
},
|
|
7817
8078
|
version: "1.0.0"
|
|
7818
8079
|
},
|
|
8080
|
+
// ─── Linear Issue ops ───
|
|
7819
8081
|
{
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
8082
|
+
action: "linear.issue.unarchive",
|
|
8083
|
+
resource_type: "linear:issue",
|
|
8084
|
+
required_relations: ["editor", "act_as"],
|
|
8085
|
+
required_scopes: ["write"],
|
|
8086
|
+
capability: "linear.write.basic",
|
|
8087
|
+
input_schema: {
|
|
8088
|
+
type: "object",
|
|
8089
|
+
properties: {
|
|
8090
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier to unarchive (e.g. ENG-123)" }
|
|
8091
|
+
},
|
|
8092
|
+
required: ["issueId"],
|
|
8093
|
+
additionalProperties: false
|
|
8094
|
+
},
|
|
8095
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8096
|
+
effects: ["Update:Issue"],
|
|
8097
|
+
risk: "high",
|
|
8098
|
+
target_bindings: {
|
|
8099
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8100
|
+
},
|
|
7823
8101
|
version: "1.0.0"
|
|
7824
|
-
}
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
}
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
}
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
}
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
|
|
7955
|
-
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
8102
|
+
},
|
|
8103
|
+
{
|
|
8104
|
+
action: "linear.issue.addLabel",
|
|
8105
|
+
resource_type: "linear:issue",
|
|
8106
|
+
required_relations: ["editor", "act_as"],
|
|
8107
|
+
required_scopes: ["write"],
|
|
8108
|
+
capability: "linear.write.basic",
|
|
8109
|
+
input_schema: {
|
|
8110
|
+
type: "object",
|
|
8111
|
+
properties: {
|
|
8112
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier" },
|
|
8113
|
+
labelId: { type: "string", minLength: 1, description: "Label ID to add" }
|
|
8114
|
+
},
|
|
8115
|
+
required: ["issueId", "labelId"],
|
|
8116
|
+
additionalProperties: false
|
|
8117
|
+
},
|
|
8118
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8119
|
+
effects: ["Update:Issue"],
|
|
8120
|
+
risk: "high",
|
|
8121
|
+
target_bindings: {
|
|
8122
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8123
|
+
},
|
|
8124
|
+
version: "1.0.0"
|
|
8125
|
+
},
|
|
8126
|
+
{
|
|
8127
|
+
action: "linear.issue.removeLabel",
|
|
8128
|
+
resource_type: "linear:issue",
|
|
8129
|
+
required_relations: ["editor", "act_as"],
|
|
8130
|
+
required_scopes: ["write"],
|
|
8131
|
+
capability: "linear.write.basic",
|
|
8132
|
+
input_schema: {
|
|
8133
|
+
type: "object",
|
|
8134
|
+
properties: {
|
|
8135
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier" },
|
|
8136
|
+
labelId: { type: "string", minLength: 1, description: "Label ID to remove" }
|
|
8137
|
+
},
|
|
8138
|
+
required: ["issueId", "labelId"],
|
|
8139
|
+
additionalProperties: false
|
|
8140
|
+
},
|
|
8141
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8142
|
+
effects: ["Update:Issue"],
|
|
8143
|
+
risk: "high",
|
|
8144
|
+
target_bindings: {
|
|
8145
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8146
|
+
},
|
|
8147
|
+
version: "1.0.0"
|
|
8148
|
+
},
|
|
8149
|
+
{
|
|
8150
|
+
action: "linear.issue.subscribe",
|
|
8151
|
+
resource_type: "linear:issue",
|
|
8152
|
+
required_relations: ["editor", "act_as"],
|
|
8153
|
+
required_scopes: ["write"],
|
|
8154
|
+
capability: "linear.write.basic",
|
|
8155
|
+
input_schema: {
|
|
8156
|
+
type: "object",
|
|
8157
|
+
properties: {
|
|
8158
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier to subscribe to" }
|
|
8159
|
+
},
|
|
8160
|
+
required: ["issueId"],
|
|
8161
|
+
additionalProperties: false
|
|
8162
|
+
},
|
|
8163
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8164
|
+
effects: ["Update:Issue"],
|
|
8165
|
+
risk: "high",
|
|
8166
|
+
target_bindings: {
|
|
8167
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8168
|
+
},
|
|
8169
|
+
version: "1.0.0"
|
|
8170
|
+
},
|
|
8171
|
+
{
|
|
8172
|
+
action: "linear.issue.delete",
|
|
8173
|
+
resource_type: "linear:issue",
|
|
8174
|
+
required_relations: ["admin", "owner", "act_as"],
|
|
8175
|
+
required_scopes: ["write"],
|
|
8176
|
+
capability: "linear.write.basic",
|
|
8177
|
+
input_schema: {
|
|
8178
|
+
type: "object",
|
|
8179
|
+
properties: {
|
|
8180
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID or identifier to permanently delete" }
|
|
8181
|
+
},
|
|
8182
|
+
required: ["issueId"],
|
|
8183
|
+
additionalProperties: false
|
|
8184
|
+
},
|
|
8185
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8186
|
+
effects: ["Delete:Issue"],
|
|
8187
|
+
risk: "critical",
|
|
8188
|
+
target_bindings: {
|
|
8189
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8190
|
+
},
|
|
8191
|
+
version: "1.0.0"
|
|
8192
|
+
},
|
|
8193
|
+
// ─── Linear Issue Relations ───
|
|
8194
|
+
{
|
|
8195
|
+
action: "linear.issueRelation.create",
|
|
8196
|
+
resource_type: "linear:issueRelation",
|
|
8197
|
+
required_relations: ["editor", "act_as"],
|
|
8198
|
+
required_scopes: ["write"],
|
|
8199
|
+
capability: "linear.write.basic",
|
|
8200
|
+
input_schema: {
|
|
8201
|
+
type: "object",
|
|
8202
|
+
properties: {
|
|
8203
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to create a relation from" },
|
|
8204
|
+
relatedIssueId: { type: "string", minLength: 1, description: "Related issue ID" },
|
|
8205
|
+
type: { type: "string", enum: ["blocks", "duplicate", "related", "similar"], description: "Relation type" }
|
|
8206
|
+
},
|
|
8207
|
+
required: ["issueId", "relatedIssueId", "type"],
|
|
8208
|
+
additionalProperties: false
|
|
8209
|
+
},
|
|
8210
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8211
|
+
effects: ["Create:IssueRelation"],
|
|
8212
|
+
risk: "high",
|
|
8213
|
+
target_bindings: {
|
|
8214
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8215
|
+
},
|
|
8216
|
+
version: "1.0.0"
|
|
8217
|
+
},
|
|
8218
|
+
{
|
|
8219
|
+
action: "linear.issueRelation.list",
|
|
8220
|
+
resource_type: "linear:issueRelation",
|
|
8221
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8222
|
+
required_scopes: ["read"],
|
|
8223
|
+
capability: "linear.read.basic",
|
|
8224
|
+
input_schema: {
|
|
8225
|
+
type: "object",
|
|
8226
|
+
properties: {
|
|
8227
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to list relations for" }
|
|
8228
|
+
},
|
|
8229
|
+
required: ["issueId"],
|
|
8230
|
+
additionalProperties: false
|
|
8231
|
+
},
|
|
8232
|
+
constraints: { rate_bucket: "linear.read" },
|
|
8233
|
+
effects: ["Read:IssueRelationList"],
|
|
8234
|
+
risk: "low",
|
|
8235
|
+
target_bindings: {
|
|
8236
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8237
|
+
},
|
|
8238
|
+
version: "1.0.0"
|
|
8239
|
+
},
|
|
8240
|
+
{
|
|
8241
|
+
action: "linear.issueRelation.delete",
|
|
8242
|
+
resource_type: "linear:issueRelation",
|
|
8243
|
+
required_relations: ["editor", "act_as"],
|
|
8244
|
+
required_scopes: ["write"],
|
|
8245
|
+
capability: "linear.write.basic",
|
|
8246
|
+
input_schema: {
|
|
8247
|
+
type: "object",
|
|
8248
|
+
properties: {
|
|
8249
|
+
relationId: { type: "string", minLength: 1, description: "Issue relation ID to delete" }
|
|
8250
|
+
},
|
|
8251
|
+
required: ["relationId"],
|
|
8252
|
+
additionalProperties: false
|
|
8253
|
+
},
|
|
8254
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8255
|
+
effects: ["Delete:IssueRelation"],
|
|
8256
|
+
risk: "high",
|
|
8257
|
+
target_bindings: {
|
|
8258
|
+
resource_id: { source: "param", param: "relationId" }
|
|
8259
|
+
},
|
|
8260
|
+
version: "1.0.0"
|
|
8261
|
+
},
|
|
8262
|
+
// ─── Linear Cycles ───
|
|
8263
|
+
{
|
|
8264
|
+
action: "linear.cycle.list",
|
|
8265
|
+
resource_type: "linear:cycle",
|
|
8266
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8267
|
+
required_scopes: ["read"],
|
|
8268
|
+
capability: "linear.read.basic",
|
|
8269
|
+
input_schema: {
|
|
8270
|
+
type: "object",
|
|
8271
|
+
properties: {
|
|
8272
|
+
teamId: { type: "string", description: "Filter by team ID" },
|
|
8273
|
+
limit: { type: "number", minimum: 1, maximum: 250, description: "Max number of cycles to return (default 50)" }
|
|
8274
|
+
},
|
|
8275
|
+
additionalProperties: false
|
|
8276
|
+
},
|
|
8277
|
+
constraints: { rate_bucket: "linear.read" },
|
|
8278
|
+
effects: ["Read:CycleList"],
|
|
8279
|
+
risk: "low",
|
|
8280
|
+
target_bindings: {
|
|
8281
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
8282
|
+
},
|
|
8283
|
+
version: "1.0.0"
|
|
8284
|
+
},
|
|
8285
|
+
{
|
|
8286
|
+
action: "linear.cycle.read",
|
|
8287
|
+
resource_type: "linear:cycle",
|
|
8288
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8289
|
+
required_scopes: ["read"],
|
|
8290
|
+
capability: "linear.read.basic",
|
|
8291
|
+
input_schema: {
|
|
8292
|
+
type: "object",
|
|
8293
|
+
properties: {
|
|
8294
|
+
cycleId: { type: "string", minLength: 1, description: "Cycle ID" }
|
|
8295
|
+
},
|
|
8296
|
+
required: ["cycleId"],
|
|
8297
|
+
additionalProperties: false
|
|
8298
|
+
},
|
|
8299
|
+
constraints: { rate_bucket: "linear.read" },
|
|
8300
|
+
effects: ["Read:Cycle"],
|
|
8301
|
+
risk: "low",
|
|
8302
|
+
target_bindings: {
|
|
8303
|
+
resource_id: { source: "param", param: "cycleId" }
|
|
8304
|
+
},
|
|
8305
|
+
version: "1.0.0"
|
|
8306
|
+
},
|
|
8307
|
+
{
|
|
8308
|
+
action: "linear.cycle.create",
|
|
8309
|
+
resource_type: "linear:cycle",
|
|
8310
|
+
required_relations: ["editor", "act_as"],
|
|
8311
|
+
required_scopes: ["write"],
|
|
8312
|
+
capability: "linear.write.basic",
|
|
8313
|
+
input_schema: {
|
|
8314
|
+
type: "object",
|
|
8315
|
+
properties: {
|
|
8316
|
+
teamId: { type: "string", minLength: 1, description: "Team ID to create the cycle in" },
|
|
8317
|
+
name: { type: "string", description: "Cycle name" },
|
|
8318
|
+
startsAt: { type: "string", minLength: 1, description: "Cycle start date (ISO 8601)" },
|
|
8319
|
+
endsAt: { type: "string", minLength: 1, description: "Cycle end date (ISO 8601)" },
|
|
8320
|
+
description: { type: "string", description: "Cycle description" }
|
|
8321
|
+
},
|
|
8322
|
+
required: ["teamId", "startsAt", "endsAt"],
|
|
8323
|
+
additionalProperties: false
|
|
8324
|
+
},
|
|
8325
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8326
|
+
effects: ["Create:Cycle"],
|
|
8327
|
+
risk: "high",
|
|
8328
|
+
target_bindings: {
|
|
8329
|
+
resource_id: { source: "param", param: "teamId" }
|
|
8330
|
+
},
|
|
8331
|
+
version: "1.0.0"
|
|
8332
|
+
},
|
|
8333
|
+
{
|
|
8334
|
+
action: "linear.cycle.update",
|
|
8335
|
+
resource_type: "linear:cycle",
|
|
8336
|
+
required_relations: ["editor", "act_as"],
|
|
8337
|
+
required_scopes: ["write"],
|
|
8338
|
+
capability: "linear.write.basic",
|
|
8339
|
+
input_schema: {
|
|
8340
|
+
type: "object",
|
|
8341
|
+
properties: {
|
|
8342
|
+
cycleId: { type: "string", minLength: 1, description: "Cycle ID to update" },
|
|
8343
|
+
name: { type: "string", description: "New cycle name" },
|
|
8344
|
+
startsAt: { type: "string", description: "New start date (ISO 8601)" },
|
|
8345
|
+
endsAt: { type: "string", description: "New end date (ISO 8601)" },
|
|
8346
|
+
description: { type: "string", description: "New description" },
|
|
8347
|
+
completedAt: { type: "string", description: "Completion date (ISO 8601) or null to unset" }
|
|
8348
|
+
},
|
|
8349
|
+
required: ["cycleId"],
|
|
8350
|
+
additionalProperties: false
|
|
8351
|
+
},
|
|
8352
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8353
|
+
effects: ["Update:Cycle"],
|
|
8354
|
+
risk: "high",
|
|
8355
|
+
target_bindings: {
|
|
8356
|
+
resource_id: { source: "param", param: "cycleId" }
|
|
8357
|
+
},
|
|
8358
|
+
version: "1.0.0"
|
|
8359
|
+
},
|
|
8360
|
+
// ─── Linear Labels ───
|
|
8361
|
+
{
|
|
8362
|
+
action: "linear.label.create",
|
|
8363
|
+
resource_type: "linear:label",
|
|
8364
|
+
required_relations: ["editor", "act_as"],
|
|
8365
|
+
required_scopes: ["write"],
|
|
8366
|
+
capability: "linear.write.basic",
|
|
8367
|
+
input_schema: {
|
|
8368
|
+
type: "object",
|
|
8369
|
+
properties: {
|
|
8370
|
+
name: { type: "string", minLength: 1, description: "Label name" },
|
|
8371
|
+
color: { type: "string", description: "Label color (hex, e.g. #FF0000)" },
|
|
8372
|
+
description: { type: "string", description: "Label description" },
|
|
8373
|
+
teamId: { type: "string", description: "Team ID to scope the label to (omit for workspace-level label)" }
|
|
8374
|
+
},
|
|
8375
|
+
required: ["name"],
|
|
8376
|
+
additionalProperties: false
|
|
8377
|
+
},
|
|
8378
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8379
|
+
effects: ["Create:Label"],
|
|
8380
|
+
risk: "high",
|
|
8381
|
+
target_bindings: {
|
|
8382
|
+
resource_id: { source: "param", param: "teamId", required: false }
|
|
8383
|
+
},
|
|
8384
|
+
version: "1.0.0"
|
|
8385
|
+
},
|
|
8386
|
+
{
|
|
8387
|
+
action: "linear.label.update",
|
|
8388
|
+
resource_type: "linear:label",
|
|
8389
|
+
required_relations: ["editor", "act_as"],
|
|
8390
|
+
required_scopes: ["write"],
|
|
8391
|
+
capability: "linear.write.basic",
|
|
8392
|
+
input_schema: {
|
|
8393
|
+
type: "object",
|
|
8394
|
+
properties: {
|
|
8395
|
+
labelId: { type: "string", minLength: 1, description: "Label ID to update" },
|
|
8396
|
+
name: { type: "string", description: "New label name" },
|
|
8397
|
+
color: { type: "string", description: "New label color (hex)" },
|
|
8398
|
+
description: { type: "string", description: "New description" }
|
|
8399
|
+
},
|
|
8400
|
+
required: ["labelId"],
|
|
8401
|
+
additionalProperties: false
|
|
8402
|
+
},
|
|
8403
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8404
|
+
effects: ["Update:Label"],
|
|
8405
|
+
risk: "high",
|
|
8406
|
+
target_bindings: {
|
|
8407
|
+
resource_id: { source: "param", param: "labelId" }
|
|
8408
|
+
},
|
|
8409
|
+
version: "1.0.0"
|
|
8410
|
+
},
|
|
8411
|
+
// ─── Linear Attachments ───
|
|
8412
|
+
{
|
|
8413
|
+
action: "linear.attachment.create",
|
|
8414
|
+
resource_type: "linear:attachment",
|
|
8415
|
+
required_relations: ["editor", "act_as"],
|
|
8416
|
+
required_scopes: ["write"],
|
|
8417
|
+
capability: "linear.write.basic",
|
|
8418
|
+
input_schema: {
|
|
8419
|
+
type: "object",
|
|
8420
|
+
properties: {
|
|
8421
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to attach to" },
|
|
8422
|
+
title: { type: "string", minLength: 1, description: "Attachment title" },
|
|
8423
|
+
url: { type: "string", minLength: 1, description: "Attachment URL" },
|
|
8424
|
+
subtitle: { type: "string", description: "Attachment subtitle" }
|
|
8425
|
+
},
|
|
8426
|
+
required: ["issueId", "title", "url"],
|
|
8427
|
+
additionalProperties: false
|
|
8428
|
+
},
|
|
8429
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8430
|
+
effects: ["Create:Attachment"],
|
|
8431
|
+
risk: "high",
|
|
8432
|
+
target_bindings: {
|
|
8433
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8434
|
+
},
|
|
8435
|
+
version: "1.0.0"
|
|
8436
|
+
},
|
|
8437
|
+
{
|
|
8438
|
+
action: "linear.attachment.list",
|
|
8439
|
+
resource_type: "linear:attachment",
|
|
8440
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8441
|
+
required_scopes: ["read"],
|
|
8442
|
+
capability: "linear.read.basic",
|
|
8443
|
+
input_schema: {
|
|
8444
|
+
type: "object",
|
|
8445
|
+
properties: {
|
|
8446
|
+
issueId: { type: "string", minLength: 1, description: "Issue ID to list attachments for" }
|
|
8447
|
+
},
|
|
8448
|
+
required: ["issueId"],
|
|
8449
|
+
additionalProperties: false
|
|
8450
|
+
},
|
|
8451
|
+
constraints: { rate_bucket: "linear.read" },
|
|
8452
|
+
effects: ["Read:AttachmentList"],
|
|
8453
|
+
risk: "low",
|
|
8454
|
+
target_bindings: {
|
|
8455
|
+
resource_id: { source: "param", param: "issueId" }
|
|
8456
|
+
},
|
|
8457
|
+
version: "1.0.0"
|
|
8458
|
+
},
|
|
8459
|
+
{
|
|
8460
|
+
action: "linear.attachment.delete",
|
|
8461
|
+
resource_type: "linear:attachment",
|
|
8462
|
+
required_relations: ["editor", "act_as"],
|
|
8463
|
+
required_scopes: ["write"],
|
|
8464
|
+
capability: "linear.write.basic",
|
|
8465
|
+
input_schema: {
|
|
8466
|
+
type: "object",
|
|
8467
|
+
properties: {
|
|
8468
|
+
attachmentId: { type: "string", minLength: 1, description: "Attachment ID to delete" }
|
|
8469
|
+
},
|
|
8470
|
+
required: ["attachmentId"],
|
|
8471
|
+
additionalProperties: false
|
|
8472
|
+
},
|
|
8473
|
+
constraints: { rate_bucket: "linear.write" },
|
|
8474
|
+
effects: ["Delete:Attachment"],
|
|
8475
|
+
risk: "high",
|
|
8476
|
+
target_bindings: {
|
|
8477
|
+
resource_id: { source: "param", param: "attachmentId" }
|
|
8478
|
+
},
|
|
8479
|
+
version: "1.0.0"
|
|
8480
|
+
},
|
|
8481
|
+
// ─── Agent Inbox Actions (internal) ───
|
|
8482
|
+
// Inbox actions back the Agent Inbox MCP tools (task delegation between
|
|
8483
|
+
// agents/people). They are internal (no external OAuth provider), so they
|
|
8484
|
+
// carry a single nominal base scope `inbox` to satisfy the registry
|
|
8485
|
+
// meta-schema's `minItems: 1` (same pattern as hubspot.account.link.get).
|
|
8486
|
+
{
|
|
8487
|
+
action: "inbox.send",
|
|
8488
|
+
resource_type: "inbox:item",
|
|
8489
|
+
required_relations: ["editor", "act_as"],
|
|
8490
|
+
required_scopes: ["inbox"],
|
|
8491
|
+
capability: "inbox.write",
|
|
8492
|
+
input_schema: {
|
|
8493
|
+
type: "object",
|
|
8494
|
+
properties: {
|
|
8495
|
+
to: { type: "string", minLength: 1, description: "Recipient (user id / handle) the task request is sent to" },
|
|
8496
|
+
taskType: { type: "string", minLength: 1, description: "Type of task being requested" },
|
|
8497
|
+
payload: { type: "object", description: "Task-specific payload data" },
|
|
8498
|
+
message: { type: "string", description: "Optional human-readable message" }
|
|
8499
|
+
},
|
|
8500
|
+
required: ["to", "taskType", "payload"],
|
|
8501
|
+
additionalProperties: false
|
|
8502
|
+
},
|
|
8503
|
+
constraints: { rate_bucket: "inbox.write" },
|
|
8504
|
+
effects: ["Create:InboxItem"],
|
|
8505
|
+
risk: "high",
|
|
8506
|
+
target_bindings: {
|
|
8507
|
+
resource_id: { source: "param", param: "to" }
|
|
8508
|
+
},
|
|
8509
|
+
version: "1.0.0"
|
|
8510
|
+
},
|
|
8511
|
+
{
|
|
8512
|
+
action: "inbox.respond",
|
|
8513
|
+
resource_type: "inbox:item",
|
|
8514
|
+
required_relations: ["editor", "act_as"],
|
|
8515
|
+
required_scopes: ["inbox"],
|
|
8516
|
+
capability: "inbox.write",
|
|
8517
|
+
input_schema: {
|
|
8518
|
+
type: "object",
|
|
8519
|
+
properties: {
|
|
8520
|
+
id: { type: "string", minLength: 1, description: "Inbox item id being responded to" },
|
|
8521
|
+
action: { type: "string", enum: ["accept", "decline", "counter"], description: "Response action" },
|
|
8522
|
+
data: { type: "object", description: "Optional response data (e.g. counter-proposal)" }
|
|
8523
|
+
},
|
|
8524
|
+
required: ["id", "action"],
|
|
8525
|
+
additionalProperties: false
|
|
8526
|
+
},
|
|
8527
|
+
constraints: { rate_bucket: "inbox.write" },
|
|
8528
|
+
effects: ["Update:InboxItem"],
|
|
8529
|
+
// high (not medium): an agent-mediated response (MCP invoke) must always
|
|
8530
|
+
// go through human approval — the Phase 1 "always confirm" guarantee made
|
|
8531
|
+
// enforceable. target_bindings below binds the concrete inbox item id so
|
|
8532
|
+
// the high-risk approval has a specific resource constraint (the public
|
|
8533
|
+
// /scheduling/:token link flow does NOT go through this gate — it calls
|
|
8534
|
+
// InboxService.respond directly, system-key-signed).
|
|
8535
|
+
risk: "high",
|
|
8536
|
+
target_bindings: {
|
|
8537
|
+
resource_id: { source: "param", param: "id" }
|
|
8538
|
+
},
|
|
8539
|
+
version: "1.0.0"
|
|
8540
|
+
},
|
|
8541
|
+
{
|
|
8542
|
+
action: "inbox.check",
|
|
8543
|
+
resource_type: "inbox:item",
|
|
8544
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8545
|
+
required_scopes: ["inbox"],
|
|
8546
|
+
capability: "inbox.read",
|
|
8547
|
+
input_schema: {
|
|
8548
|
+
type: "object",
|
|
8549
|
+
properties: {
|
|
8550
|
+
types: { type: "array", items: { type: "string" }, description: "Filter by task types" },
|
|
8551
|
+
status: { type: "string", description: "Filter by item status" }
|
|
8552
|
+
},
|
|
8553
|
+
additionalProperties: false
|
|
8554
|
+
},
|
|
8555
|
+
constraints: { rate_bucket: "inbox.read" },
|
|
8556
|
+
effects: ["Read:InboxItem"],
|
|
8557
|
+
risk: "low",
|
|
8558
|
+
target_bindings: {
|
|
8559
|
+
resource_id: { source: "param", param: "id", required: false }
|
|
8560
|
+
},
|
|
8561
|
+
version: "1.0.0"
|
|
8562
|
+
},
|
|
8563
|
+
{
|
|
8564
|
+
action: "inbox.checkByToken",
|
|
8565
|
+
resource_type: "inbox:item",
|
|
8566
|
+
required_relations: ["viewer", "editor", "admin", "owner"],
|
|
8567
|
+
required_scopes: ["inbox"],
|
|
8568
|
+
capability: "inbox.read",
|
|
8569
|
+
input_schema: {
|
|
8570
|
+
type: "object",
|
|
8571
|
+
properties: {
|
|
8572
|
+
token: { type: "string", minLength: 1, description: "Opaque access token for a single inbox item" }
|
|
8573
|
+
},
|
|
8574
|
+
required: ["token"],
|
|
8575
|
+
additionalProperties: false
|
|
8576
|
+
},
|
|
8577
|
+
constraints: { rate_bucket: "inbox.read" },
|
|
8578
|
+
effects: ["Read:InboxItem"],
|
|
8579
|
+
risk: "low",
|
|
8580
|
+
target_bindings: {
|
|
8581
|
+
// inbox.checkByToken authenticates via the opaque HMAC token itself —
|
|
8582
|
+
// the token IS the authorization credential and must NOT appear in logs
|
|
8583
|
+
// or API error responses (resolvedResourceId surfaces on resource mismatch).
|
|
8584
|
+
// This action is dispatched before requireActor() so it bypasses the
|
|
8585
|
+
// normal grant-mediated authz path entirely. We deliberately bind to a
|
|
8586
|
+
// context key that the runtime never populates so that resource_id always
|
|
8587
|
+
// resolves to null and the secret token never reaches resolvedResourceId.
|
|
8588
|
+
resource_id: { source: "context", key: "inbox_item_id" }
|
|
8589
|
+
},
|
|
8590
|
+
version: "1.0.0"
|
|
8591
|
+
},
|
|
8592
|
+
{
|
|
8593
|
+
action: "inbox.complete",
|
|
8594
|
+
resource_type: "inbox:item",
|
|
8595
|
+
required_relations: ["editor", "act_as"],
|
|
8596
|
+
required_scopes: ["inbox"],
|
|
8597
|
+
capability: "inbox.write",
|
|
8598
|
+
input_schema: {
|
|
8599
|
+
type: "object",
|
|
8600
|
+
properties: {
|
|
8601
|
+
id: { type: "string", minLength: 1, description: "Inbox item id being completed" },
|
|
8602
|
+
result: { type: "object", description: "Result payload for the completed task" }
|
|
8603
|
+
},
|
|
8604
|
+
required: ["id", "result"],
|
|
8605
|
+
additionalProperties: false
|
|
8606
|
+
},
|
|
8607
|
+
constraints: { rate_bucket: "inbox.write" },
|
|
8608
|
+
effects: ["Update:InboxItem"],
|
|
8609
|
+
// low: inbox.complete marks an inbox item as done by the owning agent —
|
|
8610
|
+
// this is an internal state update on the agent's own task list, not an
|
|
8611
|
+
// external-facing write that needs human approval. (inbox.send / inbox.respond
|
|
8612
|
+
// are high because they create messages visible to other people.)
|
|
8613
|
+
risk: "low",
|
|
8614
|
+
target_bindings: {
|
|
8615
|
+
resource_id: { source: "param", param: "id" }
|
|
8616
|
+
},
|
|
8617
|
+
version: "1.0.0"
|
|
8618
|
+
},
|
|
8619
|
+
// ─── Scheduling Actions (internal) ───
|
|
8620
|
+
// scheduling.request is a meeting-time negotiation façade over inbox.send.
|
|
8621
|
+
// Candidate slots may be supplied two ways (server-side EXCLUSIVE — exactly
|
|
8622
|
+
// one): (a) `candidates` — the agent computes them LLM-side from the user
|
|
8623
|
+
// calendar and the server validates + freebusy-filters them, or (b)
|
|
8624
|
+
// `candidateWindow` — the agent hands the server a { start, end } window and
|
|
8625
|
+
// the server generates busy-free candidates from the sender's Google
|
|
8626
|
+
// Calendar. Like the inbox actions it is internal (no external OAuth
|
|
8627
|
+
// provider), so it carries the single nominal base scope `inbox`.
|
|
8628
|
+
//
|
|
8629
|
+
// NOTE: the candidates/candidateWindow exclusivity is expressed here as
|
|
8630
|
+
// `oneOf` for documentation + the deep JSON-Schema authorities, but the SDK's
|
|
8631
|
+
// hand-written `validateActionInput` is a SHALLOW shape gate that does NOT
|
|
8632
|
+
// interpret `oneOf` (neither key is in top-level `required`). The exclusivity
|
|
8633
|
+
// (exactly one of candidates/candidateWindow) is ENFORCED server-side in
|
|
8634
|
+
// SchedulingRequestService — see that service for the 400s on both-given /
|
|
8635
|
+
// both-missing.
|
|
8636
|
+
// Spec: docs/specs/2026-06-10-inbox-intent-routing-design.md §2.1
|
|
8637
|
+
{
|
|
8638
|
+
action: "scheduling.request",
|
|
8639
|
+
resource_type: "inbox:item",
|
|
8640
|
+
required_relations: ["editor", "act_as"],
|
|
8641
|
+
required_scopes: ["inbox"],
|
|
8642
|
+
capability: "inbox.write",
|
|
8643
|
+
input_schema: {
|
|
8644
|
+
type: "object",
|
|
8645
|
+
properties: {
|
|
8646
|
+
to: { type: "string", minLength: 1, description: "Counterpart (user id / email) to negotiate a meeting time with" },
|
|
8647
|
+
topic: { type: "string", minLength: 1, description: "Meeting topic shown to the counterpart" },
|
|
8648
|
+
durationMinutes: { type: "integer", minimum: 5, maximum: 480, description: "Meeting length in minutes" },
|
|
8649
|
+
candidates: {
|
|
8650
|
+
type: "array",
|
|
8651
|
+
minItems: 1,
|
|
8652
|
+
maxItems: 10,
|
|
8653
|
+
description: "Explicit candidate slots computed by the agent from the user calendar. The server validates them AND (when Google Calendar is connected) filters out any that conflict with the sender's calendar. Mutually exclusive with candidateWindow \u2014 supply exactly one.",
|
|
8654
|
+
items: {
|
|
8655
|
+
type: "object",
|
|
8656
|
+
properties: {
|
|
8657
|
+
start: { type: "string", description: "ISO 8601 start" },
|
|
8658
|
+
end: { type: "string", description: "ISO 8601 end" }
|
|
8659
|
+
},
|
|
8660
|
+
required: ["start", "end"],
|
|
8661
|
+
additionalProperties: false
|
|
8662
|
+
}
|
|
8663
|
+
},
|
|
8664
|
+
// candidateWindow is `{start,end}` OR an ARRAY of `{start,end}` ranges
|
|
8665
|
+
// (multi-range). We declare `type: ['object', 'array']` — the SDK
|
|
8666
|
+
// shallow validator (matchesType) does not handle an ARRAY of types
|
|
8667
|
+
// (its switch is on a single string), so it hits `default: return true`
|
|
8668
|
+
// and passes BOTH the single object and the array form (B-1 — an array
|
|
8669
|
+
// must NOT be rejected before reaching the server). The union type also
|
|
8670
|
+
// keeps the AJV strict-mode meta-schema happy (a `required`/`properties`
|
|
8671
|
+
// subschema needs SOME type). The nested `properties`/`required` below
|
|
8672
|
+
// describe the object form for the deep JSON-Schema authorities; the
|
|
8673
|
+
// array element shape and the deep constraints (ISO, start<end, ≤5
|
|
8674
|
+
// ranges, ≤62-day total span) are validated server-side in
|
|
8675
|
+
// SchedulingRequestService.validateWindowRanges.
|
|
8676
|
+
candidateWindow: {
|
|
8677
|
+
type: ["object", "array"],
|
|
8678
|
+
description: 'A search window OR an ARRAY of search windows the server fills with busy-free candidate slots from the sender\'s Google Calendar. Each range is `{ start, end }` (ISO 8601) \u2014 an independent contiguous interval the server searches within, spreading candidates across ranges. "\u5E73\u65E5\u5348\u5F8C" = one range per business day (Mon 13-18 / Tue 13-18 / \u2026); "\u6708\u66DC\u5348\u524D or \u6728\u66DC\u5348\u5F8C" = two ranges. A single contiguous span = one range. Max 5 ranges, total span \u2264 62 days. Mutually exclusive with candidates \u2014 supply exactly one. Requires a connected Google Calendar.',
|
|
8679
|
+
properties: {
|
|
8680
|
+
start: { type: "string", description: "ISO 8601 range start" },
|
|
8681
|
+
end: { type: "string", description: "ISO 8601 range end" }
|
|
8682
|
+
},
|
|
8683
|
+
required: ["start", "end"],
|
|
8684
|
+
additionalProperties: false
|
|
8685
|
+
},
|
|
8686
|
+
hold: {
|
|
8687
|
+
type: "boolean",
|
|
8688
|
+
description: "When true (or omitted, when the sender's delegation policy has holds enabled), tentatively hold the offered slots on the sender's calendar as [\u4EEE] events until the counterpart responds or the request expires. Pass false to skip holds for this request. Only takes effect when the sender has an enabled scheduling delegation policy."
|
|
8689
|
+
},
|
|
8690
|
+
message: { type: "string", description: "Optional human-readable message" }
|
|
8691
|
+
},
|
|
8692
|
+
// candidates / candidateWindow are intentionally NOT in `required`: the
|
|
8693
|
+
// exclusive-choice is documented via `oneOf` and enforced server-side.
|
|
8694
|
+
// Each oneOf branch re-declares its property locally (empty `properties`
|
|
8695
|
+
// entry) so AJV strict mode (`strictRequired`) sees the required key as
|
|
8696
|
+
// defined within the branch scope — the value shape itself is validated
|
|
8697
|
+
// by the top-level `properties` above.
|
|
8698
|
+
required: ["to", "topic", "durationMinutes"],
|
|
8699
|
+
oneOf: [
|
|
8700
|
+
{ required: ["candidates"], properties: { candidates: {} } },
|
|
8701
|
+
{ required: ["candidateWindow"], properties: { candidateWindow: {} } }
|
|
8702
|
+
],
|
|
8703
|
+
additionalProperties: false
|
|
8704
|
+
},
|
|
8705
|
+
constraints: { rate_bucket: "inbox.write" },
|
|
8706
|
+
effects: ["Create:InboxItem"],
|
|
8707
|
+
risk: "high",
|
|
8708
|
+
target_bindings: {
|
|
8709
|
+
resource_id: { source: "param", param: "to" }
|
|
8710
|
+
},
|
|
8711
|
+
version: "1.0.0"
|
|
8712
|
+
}
|
|
8713
|
+
],
|
|
8714
|
+
capabilities: [
|
|
8715
|
+
{
|
|
8716
|
+
capability: "slack.messaging.basic",
|
|
8717
|
+
description: "Post, update, and delete messages in channels",
|
|
8718
|
+
includes: ["slack.message.post", "slack.message.update", "slack.message.delete"],
|
|
8719
|
+
version: "1.0.0"
|
|
8720
|
+
},
|
|
8721
|
+
{
|
|
8722
|
+
capability: "slack.read.basic",
|
|
8723
|
+
description: "Read channels, messages, and user info",
|
|
8724
|
+
includes: ["slack.channel.read", "slack.user.read", "slack.message.read", "slack.message.read_paginated", "slack.batch.read"],
|
|
8725
|
+
version: "1.0.0"
|
|
8726
|
+
},
|
|
8727
|
+
{
|
|
8728
|
+
capability: "github.read.basic",
|
|
8729
|
+
description: "Read issues, pull requests and repository contents from repositories",
|
|
8730
|
+
includes: ["github.issue.list", "github.issue.read", "github.pr.list", "github.pr.read", "github.pr.files.list", "github.pr.review.list", "github.pr.search", "github.repo.search", "github.repo.collaborator.list", "github.content.get", "github.tree.get", "github.branch.list", "github.commit.get", "github.commit.list", "github.commit.search", "github.tag.list", "github.release.list", "github.release.getLatest", "github.release.getByTag", "github.code.search", "github.issue.search", "github.issue.types.list", "github.label.get", "github.label.list", "github.workflow.get", "github.workflow.list", "github.workflow.jobLogs.get", "github.repo.starred.list", "github.user.me.get", "github.org.teams.list", "github.team.members.list", "github.user.search", "github.notification.list", "github.notification.get", "github.gist.get", "github.gist.list"],
|
|
8731
|
+
version: "1.0.0"
|
|
8732
|
+
},
|
|
8733
|
+
{
|
|
8734
|
+
capability: "github.issues.triage",
|
|
8735
|
+
description: "Create and update issues, post issue comments, manage sub-issues and labels",
|
|
8736
|
+
includes: ["github.issue.create", "github.issue.update", "github.issue.comment.create", "github.issue.subissue.write", "github.label.write"],
|
|
8737
|
+
version: "1.0.0"
|
|
8738
|
+
},
|
|
8739
|
+
{
|
|
8740
|
+
capability: "github.pulls.write",
|
|
8741
|
+
description: "Create, update, merge, and review pull requests",
|
|
8742
|
+
includes: ["github.pr.create", "github.pr.update", "github.pr.merge", "github.pr.review.create", "github.pr.comment.reply", "github.pr.branch.update"],
|
|
8743
|
+
version: "1.0.0"
|
|
8744
|
+
},
|
|
8745
|
+
{
|
|
8746
|
+
capability: "github.repos.write",
|
|
8747
|
+
description: "\u30EA\u30DD\u30B8\u30C8\u30EA\u306E\u4F5C\u6210\u30FB\u30D5\u30A9\u30FC\u30AF\u30FB\u30D5\u30A1\u30A4\u30EB\u66F4\u65B0\u30FB\u30D6\u30E9\u30F3\u30C1\u4F5C\u6210\u30FB\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u5B9F\u884C\u30FB\u30B9\u30BF\u30FC\u64CD\u4F5C",
|
|
8748
|
+
includes: ["github.repo.create", "github.repo.fork", "github.content.createOrUpdate", "github.content.delete", "github.branch.create", "github.workflow.run", "github.repo.star", "github.repo.unstar"],
|
|
8749
|
+
version: "1.0.0"
|
|
8750
|
+
},
|
|
8751
|
+
{
|
|
8752
|
+
capability: "github.notifications.write",
|
|
8753
|
+
description: "\u901A\u77E5\u306E\u65E2\u8AAD\u5316\u30FB\u30B9\u30EC\u30C3\u30C9/\u30EA\u30DD\u30B8\u30C8\u30EA\u306E\u8CFC\u8AAD\u8A2D\u5B9A",
|
|
8754
|
+
includes: ["github.notification.markRead", "github.notification.markAllRead", "github.notification.subscription.set", "github.notification.repoSubscription.set"],
|
|
8755
|
+
version: "1.0.0"
|
|
8756
|
+
},
|
|
8757
|
+
{
|
|
8758
|
+
capability: "github.gists.write",
|
|
8759
|
+
description: "Gist \u306E\u4F5C\u6210\u30FB\u66F4\u65B0",
|
|
8760
|
+
includes: ["github.gist.create", "github.gist.update"],
|
|
8761
|
+
version: "1.0.0"
|
|
8762
|
+
},
|
|
8763
|
+
{
|
|
8764
|
+
capability: "gmail.read.basic",
|
|
8765
|
+
description: "Read and search Gmail messages and labels",
|
|
8766
|
+
includes: ["gmail.message.search", "gmail.message.read", "gmail.label.read", "gmail.batch.read"],
|
|
8767
|
+
version: "1.0.0"
|
|
8768
|
+
},
|
|
8769
|
+
{
|
|
8770
|
+
capability: "gmail.compose",
|
|
8771
|
+
description: "Send emails and create drafts via Gmail",
|
|
8772
|
+
includes: ["gmail.message.send", "gmail.draft.create"],
|
|
8773
|
+
version: "1.0.0"
|
|
8774
|
+
},
|
|
8775
|
+
{
|
|
8776
|
+
capability: "gmail.manage",
|
|
8777
|
+
description: "Trash and permanently delete Gmail messages",
|
|
8778
|
+
includes: ["gmail.message.trash", "gmail.message.delete"],
|
|
8779
|
+
version: "1.0.0"
|
|
8780
|
+
},
|
|
8781
|
+
{
|
|
8782
|
+
capability: "calendar.read.basic",
|
|
8783
|
+
description: "Read and list Google Calendar events, and check free/busy availability",
|
|
8784
|
+
includes: ["calendar.event.list", "calendar.event.read", "calendar.freebusy"],
|
|
8785
|
+
version: "1.0.0"
|
|
8786
|
+
},
|
|
8787
|
+
{
|
|
8788
|
+
capability: "calendar.write",
|
|
8789
|
+
description: "Create, update, and delete Google Calendar events",
|
|
8790
|
+
includes: ["calendar.event.create", "calendar.event.update", "calendar.event.delete"],
|
|
8791
|
+
version: "1.0.0"
|
|
8792
|
+
},
|
|
8793
|
+
{
|
|
8794
|
+
capability: "jira.read.basic",
|
|
8795
|
+
description: "Read Jira issues, projects, boards, sprints, issue link types, and users",
|
|
8796
|
+
includes: ["jira.project.read", "jira.board.read", "jira.sprint.read", "jira.issue.list", "jira.issue.search", "jira.worklog.read", "jira.issue.read", "jira.batch.read", "jira.comment.read", "jira.transition.list", "jira.issuelinktype.list", "jira.user.search"],
|
|
8797
|
+
version: "1.0.0"
|
|
8798
|
+
},
|
|
8799
|
+
{
|
|
8800
|
+
capability: "jira.write.basic",
|
|
8801
|
+
description: "Create, update, delete Jira issues, manage issue links, and add/delete comments",
|
|
8802
|
+
includes: ["jira.issue.create", "jira.issue.update", "jira.issue.delete", "jira.comment.create", "jira.comment.delete", "jira.issue.transition", "jira.issuelink.create", "jira.issuelink.delete"],
|
|
8803
|
+
version: "1.0.0"
|
|
8804
|
+
},
|
|
8805
|
+
{
|
|
8806
|
+
capability: "inbox.write",
|
|
8807
|
+
description: "Send and respond to agent inbox tasks",
|
|
8808
|
+
includes: ["inbox.send", "inbox.respond", "inbox.complete", "scheduling.request"],
|
|
8809
|
+
version: "1.0.0"
|
|
8810
|
+
},
|
|
8811
|
+
{
|
|
8812
|
+
capability: "inbox.read",
|
|
8813
|
+
description: "Read agent inbox tasks",
|
|
8814
|
+
includes: ["inbox.check", "inbox.checkByToken"],
|
|
8815
|
+
version: "1.0.0"
|
|
8816
|
+
},
|
|
8817
|
+
{
|
|
8818
|
+
capability: "linear.read.basic",
|
|
8819
|
+
description: "Read Linear issues, comments, projects, teams, workflow states, labels, users, viewer info, issue relations, cycles, and attachments",
|
|
8820
|
+
includes: [
|
|
8821
|
+
"linear.issue.list",
|
|
8822
|
+
"linear.issue.read",
|
|
8823
|
+
"linear.issue.search",
|
|
8824
|
+
"linear.comment.list",
|
|
8825
|
+
"linear.project.list",
|
|
8826
|
+
"linear.project.read",
|
|
8827
|
+
"linear.team.list",
|
|
8828
|
+
"linear.workflowState.list",
|
|
8829
|
+
"linear.viewer.read",
|
|
8830
|
+
"linear.label.list",
|
|
8831
|
+
"linear.user.list",
|
|
8832
|
+
"linear.issueRelation.list",
|
|
8833
|
+
"linear.cycle.list",
|
|
8834
|
+
"linear.cycle.read",
|
|
8835
|
+
"linear.attachment.list"
|
|
8836
|
+
],
|
|
8837
|
+
version: "1.0.0"
|
|
8838
|
+
},
|
|
8839
|
+
{
|
|
8840
|
+
capability: "linear.write.basic",
|
|
8841
|
+
description: "Create, update, archive, delete Linear issues, comments, projects, labels, cycles, attachments, and issue relations",
|
|
8842
|
+
includes: [
|
|
8843
|
+
"linear.issue.create",
|
|
8844
|
+
"linear.issue.update",
|
|
8845
|
+
"linear.comment.create",
|
|
8846
|
+
"linear.issue.archive",
|
|
8847
|
+
"linear.project.create",
|
|
8848
|
+
"linear.project.update",
|
|
8849
|
+
"linear.comment.update",
|
|
8850
|
+
"linear.comment.delete",
|
|
8851
|
+
"linear.comment.resolve",
|
|
8852
|
+
"linear.comment.unresolve",
|
|
8853
|
+
"linear.issue.unarchive",
|
|
8854
|
+
"linear.issue.addLabel",
|
|
8855
|
+
"linear.issue.removeLabel",
|
|
8856
|
+
"linear.issue.subscribe",
|
|
8857
|
+
"linear.issue.delete",
|
|
8858
|
+
"linear.issueRelation.create",
|
|
8859
|
+
"linear.issueRelation.delete",
|
|
8860
|
+
"linear.cycle.create",
|
|
8861
|
+
"linear.cycle.update",
|
|
8862
|
+
"linear.label.create",
|
|
8863
|
+
"linear.label.update",
|
|
8864
|
+
"linear.attachment.create",
|
|
8865
|
+
"linear.attachment.delete"
|
|
8866
|
+
],
|
|
8867
|
+
version: "1.0.0"
|
|
8868
|
+
},
|
|
8869
|
+
{
|
|
8870
|
+
capability: "inbox.write",
|
|
8871
|
+
description: "Send and respond to agent inbox tasks",
|
|
8872
|
+
includes: ["inbox.send", "inbox.respond", "inbox.complete", "scheduling.request"],
|
|
8873
|
+
version: "1.0.0"
|
|
8874
|
+
},
|
|
8875
|
+
{
|
|
8876
|
+
capability: "inbox.read",
|
|
8877
|
+
description: "Read agent inbox tasks",
|
|
8878
|
+
includes: ["inbox.check", "inbox.checkByToken"],
|
|
8879
|
+
version: "1.0.0"
|
|
8880
|
+
}
|
|
8881
|
+
]
|
|
8882
|
+
};
|
|
8883
|
+
|
|
8884
|
+
// src/registry/resource-type-labels.ts
|
|
8885
|
+
var RESOURCE_TYPE_LABELS = {
|
|
8886
|
+
"github:repo": "\u5BFE\u8C61\u30EA\u30DD\u30B8\u30C8\u30EA",
|
|
8887
|
+
"github:org": "\u5BFE\u8C61\u7D44\u7E54"
|
|
8888
|
+
};
|
|
8889
|
+
|
|
8890
|
+
// src/registry/action-input-validator.ts
|
|
8891
|
+
var SCHEMA_INDEX = (() => {
|
|
8892
|
+
const map = /* @__PURE__ */ new Map();
|
|
8893
|
+
for (const a of ACTION_REGISTRY.actions) {
|
|
8894
|
+
if (a && typeof a.action === "string" && a.input_schema) {
|
|
8895
|
+
map.set(a.action, a.input_schema);
|
|
8896
|
+
}
|
|
8897
|
+
}
|
|
8898
|
+
return map;
|
|
8899
|
+
})();
|
|
8900
|
+
function describeExpectedShape(schema) {
|
|
8901
|
+
const props = schema.properties ?? {};
|
|
8902
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
8903
|
+
const requiredSet = new Set(required);
|
|
8904
|
+
const parts = [];
|
|
8905
|
+
const orderedKeys = [
|
|
8906
|
+
...required.filter((k) => k in props),
|
|
8907
|
+
...Object.keys(props).filter((k) => !requiredSet.has(k))
|
|
8908
|
+
];
|
|
8909
|
+
for (const key of orderedKeys) {
|
|
8910
|
+
const prop = props[key] || {};
|
|
8911
|
+
const optionalMark = requiredSet.has(key) ? "" : "?";
|
|
8912
|
+
const enumVals = Array.isArray(prop.enum) ? prop.enum : void 0;
|
|
8913
|
+
if (enumVals && enumVals.length > 0) {
|
|
8914
|
+
const rendered = enumVals.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
8915
|
+
parts.push(`${key}${optionalMark}: ${rendered}`);
|
|
8916
|
+
} else {
|
|
8917
|
+
parts.push(`${key}${optionalMark}`);
|
|
8918
|
+
}
|
|
8919
|
+
}
|
|
8920
|
+
return `{ ${parts.join(", ")} }`;
|
|
8921
|
+
}
|
|
8922
|
+
function matchesType(value, type) {
|
|
8923
|
+
if (!type) return true;
|
|
8924
|
+
switch (type) {
|
|
8925
|
+
case "string":
|
|
8926
|
+
return typeof value === "string";
|
|
8927
|
+
case "integer":
|
|
8928
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
8929
|
+
case "number":
|
|
8930
|
+
return typeof value === "number";
|
|
8931
|
+
case "boolean":
|
|
8932
|
+
return typeof value === "boolean";
|
|
8933
|
+
case "array":
|
|
8934
|
+
return Array.isArray(value);
|
|
8935
|
+
case "object":
|
|
8936
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8937
|
+
default:
|
|
8938
|
+
return true;
|
|
8939
|
+
}
|
|
8940
|
+
}
|
|
8941
|
+
function validateActionInput(action, params) {
|
|
8942
|
+
const schema = SCHEMA_INDEX.get(action);
|
|
8943
|
+
if (!schema) {
|
|
8944
|
+
return { valid: true };
|
|
8945
|
+
}
|
|
8946
|
+
const props = schema.properties ?? {};
|
|
8947
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
8948
|
+
const additionalProps = schema.additionalProperties;
|
|
8949
|
+
const safeParams = params && typeof params === "object" && !Array.isArray(params) ? params : {};
|
|
8950
|
+
const missing = [];
|
|
8951
|
+
const unknown = [];
|
|
8952
|
+
const enumErrors = [];
|
|
8953
|
+
const typeErrors = [];
|
|
8954
|
+
for (const key of required) {
|
|
8955
|
+
if (!(key in safeParams) || safeParams[key] === void 0 || safeParams[key] === null) {
|
|
8956
|
+
missing.push(key);
|
|
8957
|
+
}
|
|
8958
|
+
}
|
|
8959
|
+
if (additionalProps === false) {
|
|
8960
|
+
for (const key of Object.keys(safeParams)) {
|
|
8961
|
+
if (!(key in props)) {
|
|
8962
|
+
unknown.push(key);
|
|
8963
|
+
}
|
|
8964
|
+
}
|
|
8965
|
+
}
|
|
8966
|
+
for (const key of Object.keys(props)) {
|
|
8967
|
+
if (!(key in safeParams)) continue;
|
|
8968
|
+
const value = safeParams[key];
|
|
8969
|
+
if (value === void 0 || value === null) continue;
|
|
8970
|
+
const prop = props[key] || {};
|
|
8971
|
+
const enumVals = Array.isArray(prop.enum) ? prop.enum : void 0;
|
|
8972
|
+
if (enumVals && enumVals.length > 0) {
|
|
8973
|
+
if (!enumVals.includes(value)) {
|
|
8974
|
+
enumErrors.push(key);
|
|
8975
|
+
continue;
|
|
8976
|
+
}
|
|
8977
|
+
}
|
|
8978
|
+
if (!matchesType(value, prop.type)) {
|
|
8979
|
+
typeErrors.push(key);
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8982
|
+
if (missing.length === 0 && unknown.length === 0 && enumErrors.length === 0 && typeErrors.length === 0) {
|
|
8983
|
+
return { valid: true };
|
|
8984
|
+
}
|
|
8985
|
+
const segments = [];
|
|
8986
|
+
if (missing.length > 0) {
|
|
8987
|
+
segments.push(`missing required parameter(s) [${missing.join(", ")}]`);
|
|
8988
|
+
}
|
|
8989
|
+
if (unknown.length > 0) {
|
|
8990
|
+
segments.push(`unknown parameter(s) [${unknown.join(", ")}]`);
|
|
8991
|
+
}
|
|
8992
|
+
if (enumErrors.length > 0) {
|
|
8993
|
+
const details = enumErrors.map((key) => {
|
|
8994
|
+
const enumVals = props[key]?.enum || [];
|
|
8995
|
+
const rendered = enumVals.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
8996
|
+
return `${key} (allowed: ${rendered})`;
|
|
8997
|
+
}).join(", ");
|
|
8998
|
+
segments.push(`invalid value for enum parameter(s) [${details}]`);
|
|
8999
|
+
}
|
|
9000
|
+
if (typeErrors.length > 0) {
|
|
9001
|
+
const details = typeErrors.map((key) => `${key} (expected ${props[key]?.type})`).join(", ");
|
|
9002
|
+
segments.push(`wrong type for parameter(s) [${details}]`);
|
|
9003
|
+
}
|
|
9004
|
+
const message = `${action}: ${segments.join("; ")}. Expected shape: ${describeExpectedShape(schema)}`;
|
|
9005
|
+
return { valid: false, errors: [message] };
|
|
9006
|
+
}
|
|
9007
|
+
|
|
9008
|
+
// src/registry/resource-types.ts
|
|
9009
|
+
var RESOURCE_TYPES = {
|
|
9010
|
+
// Slack
|
|
9011
|
+
SLACK_CHANNEL: "slack:channel",
|
|
9012
|
+
SLACK_USER: "slack:user",
|
|
9013
|
+
SLACK_WORKSPACE: "slack:workspace",
|
|
9014
|
+
// GitHub
|
|
9015
|
+
GITHUB_REPO: "github:repo",
|
|
9016
|
+
GITHUB_ORG: "github:org",
|
|
9017
|
+
GITHUB_ISSUE: "github:issue",
|
|
9018
|
+
// Google Drive
|
|
9019
|
+
GOOGLE_DRIVE_FILE: "google:drive:file",
|
|
9020
|
+
GOOGLE_DRIVE_FOLDER: "google:drive:folder",
|
|
9021
|
+
// Gmail
|
|
9022
|
+
GMAIL_THREAD: "gmail:thread",
|
|
9023
|
+
GMAIL_LABEL: "gmail:label",
|
|
9024
|
+
// Jira
|
|
9025
|
+
JIRA_PROJECT: "jira:project",
|
|
9026
|
+
JIRA_BOARD: "jira:board",
|
|
9027
|
+
JIRA_ISSUE: "jira:issue",
|
|
9028
|
+
JIRA_SPRINT: "jira:sprint",
|
|
9029
|
+
// HubSpot
|
|
9030
|
+
HUBSPOT_OBJECT: "hubspot:object",
|
|
9031
|
+
HUBSPOT_PROPERTY: "hubspot:property",
|
|
9032
|
+
HUBSPOT_SCHEMA: "hubspot:schema",
|
|
9033
|
+
HUBSPOT_ASSOCIATION: "hubspot:association",
|
|
9034
|
+
HUBSPOT_ENGAGEMENT: "hubspot:engagement",
|
|
9035
|
+
HUBSPOT_WORKFLOW: "hubspot:workflow",
|
|
9036
|
+
HUBSPOT_ACCOUNT: "hubspot:account",
|
|
9037
|
+
// OS (local)
|
|
9038
|
+
OS_SECRET: "os:secret",
|
|
9039
|
+
OS_PROCESS: "os:process",
|
|
9040
|
+
// Wildcard
|
|
9041
|
+
ANY: "*"
|
|
9042
|
+
};
|
|
9043
|
+
var LEGACY_RESOURCE_TYPE_MAP = {
|
|
9044
|
+
// Action Registry CamelCase format
|
|
9045
|
+
SlackChannel: RESOURCE_TYPES.SLACK_CHANNEL,
|
|
9046
|
+
GitHubRepo: RESOURCE_TYPES.GITHUB_REPO,
|
|
7991
9047
|
DriveFile: RESOURCE_TYPES.GOOGLE_DRIVE_FILE,
|
|
7992
9048
|
JiraIssue: RESOURCE_TYPES.JIRA_ISSUE,
|
|
7993
9049
|
JiraProject: RESOURCE_TYPES.JIRA_PROJECT,
|
|
@@ -8195,188 +9251,773 @@ var ACTION_DISPLAY_CONFIGS = {
|
|
|
8195
9251
|
"slack.message.post": {
|
|
8196
9252
|
summaryTemplate: (p) => {
|
|
8197
9253
|
const parts = [];
|
|
8198
|
-
if (p.channel) parts.push(p.channel + ":");
|
|
8199
|
-
if (p.text) parts.push(String(p.text));
|
|
9254
|
+
if (p.channel) parts.push(p.channel + ":");
|
|
9255
|
+
if (p.text) parts.push(String(p.text));
|
|
9256
|
+
return parts.join(" ");
|
|
9257
|
+
},
|
|
9258
|
+
displayFields: [
|
|
9259
|
+
{ key: "channel", label: "Channel" },
|
|
9260
|
+
{ key: "text", label: "Message" }
|
|
9261
|
+
]
|
|
9262
|
+
},
|
|
9263
|
+
"gmail.message.send": {
|
|
9264
|
+
summaryTemplate: (p) => {
|
|
9265
|
+
const parts = [];
|
|
9266
|
+
if (p.to) parts.push(`To: ${p.to}`);
|
|
9267
|
+
if (p.subject) parts.push(`Subject: ${p.subject}`);
|
|
9268
|
+
return parts.join(", ");
|
|
9269
|
+
},
|
|
9270
|
+
displayFields: [
|
|
9271
|
+
{ key: "to", label: "To" },
|
|
9272
|
+
{ key: "subject", label: "Subject" },
|
|
9273
|
+
{ key: "body", label: "Body" }
|
|
9274
|
+
]
|
|
9275
|
+
},
|
|
9276
|
+
"gmail.draft.create": {
|
|
9277
|
+
summaryTemplate: (p) => {
|
|
9278
|
+
const parts = [];
|
|
9279
|
+
if (p.to) parts.push(`To: ${p.to}`);
|
|
9280
|
+
if (p.subject) parts.push(`Subject: ${p.subject}`);
|
|
9281
|
+
return parts.join(", ");
|
|
9282
|
+
},
|
|
9283
|
+
displayFields: [
|
|
9284
|
+
{ key: "to", label: "To" },
|
|
9285
|
+
{ key: "subject", label: "Subject" },
|
|
9286
|
+
{ key: "body", label: "Body" }
|
|
9287
|
+
]
|
|
9288
|
+
},
|
|
9289
|
+
"calendar.event.create": {
|
|
9290
|
+
summaryTemplate: (p) => {
|
|
9291
|
+
const parts = [];
|
|
9292
|
+
if (p.summary) parts.push(p.summary);
|
|
9293
|
+
if (p.start) parts.push(`(${formatCalendarTime(p.start)})`);
|
|
9294
|
+
return parts.join(" ");
|
|
9295
|
+
},
|
|
9296
|
+
displayFields: [
|
|
9297
|
+
{ key: "summary", label: "Event" },
|
|
9298
|
+
{ key: "start", label: "Start" },
|
|
9299
|
+
{ key: "end", label: "End" },
|
|
9300
|
+
{ key: "attendees", label: "Attendees" }
|
|
9301
|
+
]
|
|
9302
|
+
},
|
|
9303
|
+
"calendar.event.update": {
|
|
9304
|
+
summaryTemplate: (p) => {
|
|
9305
|
+
const parts = [];
|
|
9306
|
+
if (p.summary) parts.push(p.summary);
|
|
9307
|
+
if (p.start) parts.push(`(${formatCalendarTime(p.start)})`);
|
|
9308
|
+
return parts.join(" ");
|
|
9309
|
+
},
|
|
9310
|
+
displayFields: [
|
|
9311
|
+
{ key: "summary", label: "Event" },
|
|
9312
|
+
{ key: "start", label: "Start" },
|
|
9313
|
+
{ key: "end", label: "End" },
|
|
9314
|
+
{ key: "attendees", label: "Attendees" }
|
|
9315
|
+
]
|
|
9316
|
+
},
|
|
9317
|
+
"jira.issue.create": {
|
|
9318
|
+
summaryTemplate: (p) => {
|
|
9319
|
+
const parts = [];
|
|
9320
|
+
const projectKey = jiraField(
|
|
9321
|
+
p,
|
|
9322
|
+
["projectKey", "project"],
|
|
9323
|
+
"project",
|
|
9324
|
+
(v) => typeof v === "string" ? v : v?.key
|
|
9325
|
+
);
|
|
9326
|
+
const summary = jiraField(p, ["summary"], "summary");
|
|
9327
|
+
if (projectKey) parts.push(`${projectKey}:`);
|
|
9328
|
+
if (summary) parts.push(summary);
|
|
9329
|
+
return parts.join(" ");
|
|
9330
|
+
},
|
|
9331
|
+
// AIDENTITY-54: nested `fields.X` 形式と top-level canonical の両方を
|
|
9332
|
+
// 拾えるよう extract を使う。assignee は null (unassign) も表示。
|
|
9333
|
+
// legacy alias (project / issuetype 等) も top-level 候補に含めて後方互換を保つ。
|
|
9334
|
+
displayFields: [
|
|
9335
|
+
{
|
|
9336
|
+
label: "Project",
|
|
9337
|
+
extract: (p) => jiraField(
|
|
9338
|
+
p,
|
|
9339
|
+
["projectKey", "project"],
|
|
9340
|
+
"project",
|
|
9341
|
+
(v) => typeof v === "string" ? v : v?.key
|
|
9342
|
+
)
|
|
9343
|
+
},
|
|
9344
|
+
{
|
|
9345
|
+
label: "Type",
|
|
9346
|
+
extract: (p) => jiraField(
|
|
9347
|
+
p,
|
|
9348
|
+
["issueTypeName", "issueType", "issuetype"],
|
|
9349
|
+
"issuetype",
|
|
9350
|
+
(v) => typeof v === "string" ? v : v?.name
|
|
9351
|
+
)
|
|
9352
|
+
},
|
|
9353
|
+
{ label: "Summary", extract: (p) => jiraField(p, ["summary"], "summary") },
|
|
9354
|
+
{ label: "Description", extract: (p) => jiraField(p, ["description"], "description") },
|
|
9355
|
+
{
|
|
9356
|
+
label: "Priority",
|
|
9357
|
+
extract: (p) => jiraField(
|
|
9358
|
+
p,
|
|
9359
|
+
["priority"],
|
|
9360
|
+
"priority",
|
|
9361
|
+
(v) => typeof v === "string" ? v : v?.name
|
|
9362
|
+
)
|
|
9363
|
+
},
|
|
9364
|
+
{ label: "Assignee", extract: extractJiraAssigneeDisplay },
|
|
9365
|
+
{ label: "Labels", extract: (p) => jiraField(p, ["labels"], "labels") }
|
|
9366
|
+
]
|
|
9367
|
+
},
|
|
9368
|
+
"jira.issue.update": {
|
|
9369
|
+
summaryTemplate: (p) => {
|
|
9370
|
+
const parts = [];
|
|
9371
|
+
const key = p.issueIdOrKey ?? p.issueKey;
|
|
9372
|
+
const summary = jiraField(p, ["summary"], "summary");
|
|
9373
|
+
if (key) parts.push(`${key}:`);
|
|
9374
|
+
if (summary) parts.push(summary);
|
|
9375
|
+
return parts.join(" ");
|
|
9376
|
+
},
|
|
9377
|
+
displayFields: [
|
|
9378
|
+
// canonical は issueIdOrKey、agent が issueKey で送ってくる旧仕様も拾う。
|
|
9379
|
+
{ label: "Issue", extract: (p) => p.issueIdOrKey ?? p.issueKey },
|
|
9380
|
+
{ label: "Summary", extract: (p) => jiraField(p, ["summary"], "summary") },
|
|
9381
|
+
{ label: "Description", extract: (p) => jiraField(p, ["description"], "description") },
|
|
9382
|
+
{
|
|
9383
|
+
label: "Priority",
|
|
9384
|
+
extract: (p) => jiraField(
|
|
9385
|
+
p,
|
|
9386
|
+
["priority"],
|
|
9387
|
+
"priority",
|
|
9388
|
+
(v) => typeof v === "string" ? v : v?.name
|
|
9389
|
+
)
|
|
9390
|
+
},
|
|
9391
|
+
// AIDENTITY-54: top-level alias (string / object) と null (unassign) も解決。
|
|
9392
|
+
{ label: "Assignee", extract: extractJiraAssigneeDisplay },
|
|
9393
|
+
{ label: "Labels", extract: (p) => jiraField(p, ["labels"], "labels") }
|
|
9394
|
+
]
|
|
9395
|
+
},
|
|
9396
|
+
// AIDENTITY-65: comment 本体は string と ADF document の両方を受けるため、
|
|
9397
|
+
// detail 表示の ADF 描画は formatValueFull 側に任せて key 指定で OK。
|
|
9398
|
+
"jira.comment.create": {
|
|
9399
|
+
summaryTemplate: (p) => {
|
|
9400
|
+
const parts = [];
|
|
9401
|
+
if (p.issueIdOrKey) parts.push(`${p.issueIdOrKey}:`);
|
|
9402
|
+
if (p.body) parts.push(typeof p.body === "string" ? p.body : "[ADF]");
|
|
9403
|
+
return parts.join(" ");
|
|
9404
|
+
},
|
|
9405
|
+
displayFields: [
|
|
9406
|
+
{ key: "issueIdOrKey", label: "Issue" },
|
|
9407
|
+
{ key: "body", label: "Comment" }
|
|
9408
|
+
]
|
|
9409
|
+
},
|
|
9410
|
+
// AIDENTITY-66: 破壊的操作なので「どの issue のどの comment を消すか」を明示する
|
|
9411
|
+
// (jira.issue.delete / jira.issuelink.delete と同じ destructive 表現の方針)。
|
|
9412
|
+
"jira.comment.delete": {
|
|
9413
|
+
summaryTemplate: (p) => {
|
|
9414
|
+
const issue = p.issueIdOrKey ?? p.issueKey;
|
|
9415
|
+
const commentId = p.commentId ?? p.id;
|
|
9416
|
+
if (issue && commentId) return `Delete comment ${commentId} on ${issue}`;
|
|
9417
|
+
if (commentId) return `Delete comment ${commentId}`;
|
|
9418
|
+
return "";
|
|
9419
|
+
},
|
|
9420
|
+
displayFields: [
|
|
9421
|
+
{ label: "Issue", extract: (p) => p.issueIdOrKey ?? p.issueKey },
|
|
9422
|
+
{ label: "Comment", extract: (p) => p.commentId ?? p.id }
|
|
9423
|
+
]
|
|
9424
|
+
},
|
|
9425
|
+
// AIDENTITY-65: API enricher が 'Link' label を upsert で書き換える。
|
|
9426
|
+
"jira.issuelink.delete": {
|
|
9427
|
+
summaryTemplate: (p) => {
|
|
9428
|
+
const parts = [];
|
|
9429
|
+
if (p.linkId) parts.push(`Delete link ${p.linkId}`);
|
|
9430
|
+
return parts.join(" ");
|
|
9431
|
+
},
|
|
9432
|
+
displayFields: [
|
|
9433
|
+
{ key: "linkId", label: "Link" }
|
|
9434
|
+
]
|
|
9435
|
+
},
|
|
9436
|
+
// ─── HubSpot ───
|
|
9437
|
+
"hubspot.crm.objects.list": {
|
|
9438
|
+
summaryTemplate: (p) => {
|
|
9439
|
+
const parts = [];
|
|
9440
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9441
|
+
parts.push("list");
|
|
9442
|
+
return parts.join(" ");
|
|
9443
|
+
},
|
|
9444
|
+
displayFields: [
|
|
9445
|
+
{ key: "objectType", label: "Object Type" },
|
|
9446
|
+
{ key: "limit", label: "Limit" },
|
|
9447
|
+
{ key: "properties", label: "Properties" }
|
|
9448
|
+
]
|
|
9449
|
+
},
|
|
9450
|
+
"hubspot.crm.objects.search": {
|
|
9451
|
+
summaryTemplate: (p) => {
|
|
9452
|
+
const parts = [];
|
|
9453
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9454
|
+
if (p.query) parts.push(`"${String(p.query)}"`);
|
|
9455
|
+
return parts.join(" ");
|
|
9456
|
+
},
|
|
9457
|
+
displayFields: [
|
|
9458
|
+
{ key: "objectType", label: "Object Type" },
|
|
9459
|
+
{ key: "query", label: "Query" },
|
|
9460
|
+
{ key: "limit", label: "Limit" }
|
|
9461
|
+
]
|
|
9462
|
+
},
|
|
9463
|
+
"hubspot.crm.objects.batchRead": {
|
|
9464
|
+
summaryTemplate: (p) => {
|
|
9465
|
+
const parts = [];
|
|
9466
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9467
|
+
if (Array.isArray(p.inputs)) parts.push(`(${p.inputs.length} items)`);
|
|
9468
|
+
return parts.join(" ");
|
|
9469
|
+
},
|
|
9470
|
+
displayFields: [
|
|
9471
|
+
{ key: "objectType", label: "Object Type" },
|
|
9472
|
+
{ key: "inputs", label: "Records" }
|
|
9473
|
+
]
|
|
9474
|
+
},
|
|
9475
|
+
"hubspot.crm.objects.batchCreate": {
|
|
9476
|
+
summaryTemplate: (p) => {
|
|
9477
|
+
const parts = [];
|
|
9478
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9479
|
+
if (Array.isArray(p.inputs)) parts.push(`create ${p.inputs.length}`);
|
|
9480
|
+
return parts.join(" ");
|
|
9481
|
+
},
|
|
9482
|
+
displayFields: [
|
|
9483
|
+
{ key: "objectType", label: "Object Type" },
|
|
9484
|
+
{ key: "inputs", label: "Records" }
|
|
9485
|
+
]
|
|
9486
|
+
},
|
|
9487
|
+
"hubspot.crm.objects.batchUpdate": {
|
|
9488
|
+
summaryTemplate: (p) => {
|
|
9489
|
+
const parts = [];
|
|
9490
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9491
|
+
if (Array.isArray(p.inputs)) parts.push(`update ${p.inputs.length}`);
|
|
9492
|
+
return parts.join(" ");
|
|
9493
|
+
},
|
|
9494
|
+
displayFields: [
|
|
9495
|
+
{ key: "objectType", label: "Object Type" },
|
|
9496
|
+
{ key: "inputs", label: "Records" }
|
|
9497
|
+
]
|
|
9498
|
+
},
|
|
9499
|
+
"hubspot.crm.properties.list": {
|
|
9500
|
+
summaryTemplate: (p) => {
|
|
9501
|
+
const parts = [];
|
|
9502
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9503
|
+
parts.push("properties list");
|
|
9504
|
+
return parts.join(" ");
|
|
9505
|
+
},
|
|
9506
|
+
displayFields: [
|
|
9507
|
+
{ key: "objectType", label: "Object Type" }
|
|
9508
|
+
]
|
|
9509
|
+
},
|
|
9510
|
+
"hubspot.crm.properties.create": {
|
|
9511
|
+
summaryTemplate: (p) => {
|
|
9512
|
+
const parts = [];
|
|
9513
|
+
if (p.objectType) parts.push(String(p.objectType));
|
|
9514
|
+
if (p.name) parts.push(String(p.name));
|
|
9515
|
+
return parts.join(" ");
|
|
9516
|
+
},
|
|
9517
|
+
displayFields: [
|
|
9518
|
+
{ key: "objectType", label: "Object Type" },
|
|
9519
|
+
{ key: "name", label: "Property Name" },
|
|
9520
|
+
{ key: "label", label: "Label" },
|
|
9521
|
+
{ key: "type", label: "Type" }
|
|
9522
|
+
]
|
|
9523
|
+
},
|
|
9524
|
+
"hubspot.crm.engagements.create": {
|
|
9525
|
+
summaryTemplate: (p) => {
|
|
9526
|
+
const parts = [];
|
|
9527
|
+
if (p.type) parts.push(String(p.type));
|
|
9528
|
+
parts.push("engagement");
|
|
9529
|
+
return parts.join(" ");
|
|
9530
|
+
},
|
|
9531
|
+
displayFields: [
|
|
9532
|
+
{ key: "type", label: "Type" },
|
|
9533
|
+
{ key: "metadata", label: "Metadata" }
|
|
9534
|
+
]
|
|
9535
|
+
},
|
|
9536
|
+
"hubspot.automation.workflows.list": {
|
|
9537
|
+
summaryTemplate: (_p) => "List workflows",
|
|
9538
|
+
displayFields: [
|
|
9539
|
+
{ key: "limit", label: "Limit" }
|
|
9540
|
+
]
|
|
9541
|
+
},
|
|
9542
|
+
"hubspot.account.userDetails.get": {
|
|
9543
|
+
summaryTemplate: (_p) => "Get HubSpot account details",
|
|
9544
|
+
displayFields: []
|
|
9545
|
+
},
|
|
9546
|
+
"hubspot.account.link.get": {
|
|
9547
|
+
summaryTemplate: (p) => {
|
|
9548
|
+
const parts = [];
|
|
9549
|
+
if (p.portalId) parts.push(`portal:${p.portalId}`);
|
|
9550
|
+
if (Array.isArray(p.pageRequests)) parts.push(`(${p.pageRequests.length} links)`);
|
|
9551
|
+
return parts.join(" ");
|
|
9552
|
+
},
|
|
9553
|
+
displayFields: [
|
|
9554
|
+
{ key: "portalId", label: "Portal ID" },
|
|
9555
|
+
{ key: "pageRequests", label: "Page Requests" }
|
|
9556
|
+
]
|
|
9557
|
+
},
|
|
9558
|
+
// ─── Linear ───
|
|
9559
|
+
"linear.issue.create": {
|
|
9560
|
+
summaryTemplate: (p) => {
|
|
9561
|
+
const parts = [];
|
|
9562
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9563
|
+
if (p.title) parts.push(String(p.title));
|
|
9564
|
+
return parts.join(" ");
|
|
9565
|
+
},
|
|
9566
|
+
displayFields: [
|
|
9567
|
+
{ key: "teamId", label: "Team" },
|
|
9568
|
+
{ key: "title", label: "Title" },
|
|
9569
|
+
{ key: "description", label: "Description" },
|
|
9570
|
+
{ key: "stateId", label: "State" },
|
|
9571
|
+
{ key: "assigneeId", label: "Assignee" },
|
|
9572
|
+
{ key: "priority", label: "Priority" },
|
|
9573
|
+
{ key: "labelIds", label: "Labels" }
|
|
9574
|
+
]
|
|
9575
|
+
},
|
|
9576
|
+
"linear.issue.update": {
|
|
9577
|
+
summaryTemplate: (p) => {
|
|
9578
|
+
const parts = [];
|
|
9579
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9580
|
+
if (p.title) parts.push(String(p.title));
|
|
9581
|
+
return parts.join(" ");
|
|
9582
|
+
},
|
|
9583
|
+
displayFields: [
|
|
9584
|
+
{ key: "issueId", label: "Issue" },
|
|
9585
|
+
{ key: "title", label: "Title" },
|
|
9586
|
+
{ key: "description", label: "Description" },
|
|
9587
|
+
{ key: "stateId", label: "State" },
|
|
9588
|
+
{ key: "assigneeId", label: "Assignee" },
|
|
9589
|
+
{ key: "priority", label: "Priority" },
|
|
9590
|
+
{ key: "labelIds", label: "Labels" }
|
|
9591
|
+
]
|
|
9592
|
+
},
|
|
9593
|
+
"linear.comment.create": {
|
|
9594
|
+
summaryTemplate: (p) => {
|
|
9595
|
+
const parts = [];
|
|
9596
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9597
|
+
if (p.body) parts.push(String(p.body));
|
|
9598
|
+
return parts.join(" ");
|
|
9599
|
+
},
|
|
9600
|
+
displayFields: [
|
|
9601
|
+
{ key: "issueId", label: "Issue" },
|
|
9602
|
+
{ key: "body", label: "Comment" }
|
|
9603
|
+
]
|
|
9604
|
+
},
|
|
9605
|
+
"linear.issue.archive": {
|
|
9606
|
+
summaryTemplate: (p) => {
|
|
9607
|
+
const parts = [];
|
|
9608
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9609
|
+
parts.push("Archive");
|
|
9610
|
+
return parts.join(" ");
|
|
9611
|
+
},
|
|
9612
|
+
displayFields: [
|
|
9613
|
+
{ key: "issueId", label: "Issue" }
|
|
9614
|
+
]
|
|
9615
|
+
},
|
|
9616
|
+
"linear.label.list": {
|
|
9617
|
+
summaryTemplate: (p) => {
|
|
9618
|
+
const parts = [];
|
|
9619
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9620
|
+
parts.push("List labels");
|
|
9621
|
+
return parts.join(" ");
|
|
9622
|
+
},
|
|
9623
|
+
displayFields: [
|
|
9624
|
+
{ key: "teamId", label: "Team" },
|
|
9625
|
+
{ key: "limit", label: "Limit" }
|
|
9626
|
+
]
|
|
9627
|
+
},
|
|
9628
|
+
"linear.user.list": {
|
|
9629
|
+
summaryTemplate: (p) => {
|
|
9630
|
+
const parts = [];
|
|
9631
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9632
|
+
parts.push("List users");
|
|
9633
|
+
return parts.join(" ");
|
|
9634
|
+
},
|
|
9635
|
+
displayFields: [
|
|
9636
|
+
{ key: "teamId", label: "Team" },
|
|
9637
|
+
{ key: "limit", label: "Limit" }
|
|
9638
|
+
]
|
|
9639
|
+
},
|
|
9640
|
+
"linear.project.create": {
|
|
9641
|
+
summaryTemplate: (p) => {
|
|
9642
|
+
const parts = [];
|
|
9643
|
+
if (p.teamIds) parts.push(`${Array.isArray(p.teamIds) ? p.teamIds.join(",") : String(p.teamIds)}:`);
|
|
9644
|
+
if (p.name) parts.push(String(p.name));
|
|
9645
|
+
return parts.join(" ");
|
|
9646
|
+
},
|
|
9647
|
+
displayFields: [
|
|
9648
|
+
{ key: "teamIds", label: "Teams" },
|
|
9649
|
+
{ key: "name", label: "Name" },
|
|
9650
|
+
{ key: "description", label: "Description" },
|
|
9651
|
+
{ key: "statusId", label: "Status ID" },
|
|
9652
|
+
{ key: "startDate", label: "Start Date" },
|
|
9653
|
+
{ key: "targetDate", label: "Target Date" }
|
|
9654
|
+
]
|
|
9655
|
+
},
|
|
9656
|
+
"linear.project.update": {
|
|
9657
|
+
summaryTemplate: (p) => {
|
|
9658
|
+
const parts = [];
|
|
9659
|
+
if (p.projectId) parts.push(`${p.projectId}:`);
|
|
9660
|
+
if (p.name) parts.push(String(p.name));
|
|
9661
|
+
return parts.join(" ");
|
|
9662
|
+
},
|
|
9663
|
+
displayFields: [
|
|
9664
|
+
{ key: "projectId", label: "Project" },
|
|
9665
|
+
{ key: "name", label: "Name" },
|
|
9666
|
+
{ key: "description", label: "Description" },
|
|
9667
|
+
{ key: "statusId", label: "Status ID" },
|
|
9668
|
+
{ key: "startDate", label: "Start Date" },
|
|
9669
|
+
{ key: "targetDate", label: "Target Date" }
|
|
9670
|
+
]
|
|
9671
|
+
},
|
|
9672
|
+
// ─── Linear Comment ops ───
|
|
9673
|
+
"linear.comment.update": {
|
|
9674
|
+
summaryTemplate: (p) => {
|
|
9675
|
+
const parts = [];
|
|
9676
|
+
if (p.commentId) parts.push(`${p.commentId}:`);
|
|
9677
|
+
parts.push("Update comment");
|
|
9678
|
+
return parts.join(" ");
|
|
9679
|
+
},
|
|
9680
|
+
displayFields: [
|
|
9681
|
+
{ key: "commentId", label: "Comment" },
|
|
9682
|
+
{ key: "body", label: "Body" }
|
|
9683
|
+
]
|
|
9684
|
+
},
|
|
9685
|
+
"linear.comment.delete": {
|
|
9686
|
+
summaryTemplate: (p) => {
|
|
9687
|
+
const parts = [];
|
|
9688
|
+
if (p.commentId) parts.push(`Delete comment ${p.commentId}`);
|
|
8200
9689
|
return parts.join(" ");
|
|
8201
9690
|
},
|
|
8202
9691
|
displayFields: [
|
|
8203
|
-
{ key: "
|
|
8204
|
-
{ key: "text", label: "Message" }
|
|
9692
|
+
{ key: "commentId", label: "Comment" }
|
|
8205
9693
|
]
|
|
8206
9694
|
},
|
|
8207
|
-
"
|
|
9695
|
+
"linear.comment.resolve": {
|
|
8208
9696
|
summaryTemplate: (p) => {
|
|
8209
9697
|
const parts = [];
|
|
8210
|
-
if (p.
|
|
8211
|
-
|
|
8212
|
-
return parts.join("
|
|
9698
|
+
if (p.commentId) parts.push(`${p.commentId}:`);
|
|
9699
|
+
parts.push("Resolve comment");
|
|
9700
|
+
return parts.join(" ");
|
|
8213
9701
|
},
|
|
8214
9702
|
displayFields: [
|
|
8215
|
-
{ key: "
|
|
8216
|
-
{ key: "subject", label: "Subject" },
|
|
8217
|
-
{ key: "body", label: "Body" }
|
|
9703
|
+
{ key: "commentId", label: "Comment" }
|
|
8218
9704
|
]
|
|
8219
9705
|
},
|
|
8220
|
-
"
|
|
9706
|
+
"linear.comment.unresolve": {
|
|
8221
9707
|
summaryTemplate: (p) => {
|
|
8222
9708
|
const parts = [];
|
|
8223
|
-
if (p.
|
|
8224
|
-
|
|
8225
|
-
return parts.join("
|
|
9709
|
+
if (p.commentId) parts.push(`${p.commentId}:`);
|
|
9710
|
+
parts.push("Unresolve comment");
|
|
9711
|
+
return parts.join(" ");
|
|
8226
9712
|
},
|
|
8227
9713
|
displayFields: [
|
|
8228
|
-
{ key: "
|
|
8229
|
-
{ key: "subject", label: "Subject" },
|
|
8230
|
-
{ key: "body", label: "Body" }
|
|
9714
|
+
{ key: "commentId", label: "Comment" }
|
|
8231
9715
|
]
|
|
8232
9716
|
},
|
|
8233
|
-
|
|
9717
|
+
// ─── Linear Issue ops ───
|
|
9718
|
+
"linear.issue.unarchive": {
|
|
8234
9719
|
summaryTemplate: (p) => {
|
|
8235
9720
|
const parts = [];
|
|
8236
|
-
if (p.
|
|
8237
|
-
|
|
9721
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9722
|
+
parts.push("Unarchive");
|
|
8238
9723
|
return parts.join(" ");
|
|
8239
9724
|
},
|
|
8240
9725
|
displayFields: [
|
|
8241
|
-
{ key: "
|
|
8242
|
-
{ key: "start", label: "Start" },
|
|
8243
|
-
{ key: "end", label: "End" },
|
|
8244
|
-
{ key: "attendees", label: "Attendees" }
|
|
9726
|
+
{ key: "issueId", label: "Issue" }
|
|
8245
9727
|
]
|
|
8246
9728
|
},
|
|
8247
|
-
"
|
|
9729
|
+
"linear.issue.addLabel": {
|
|
8248
9730
|
summaryTemplate: (p) => {
|
|
8249
9731
|
const parts = [];
|
|
8250
|
-
if (p.
|
|
8251
|
-
if (p.
|
|
9732
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9733
|
+
if (p.labelId) parts.push(`Add label ${p.labelId}`);
|
|
8252
9734
|
return parts.join(" ");
|
|
8253
9735
|
},
|
|
8254
9736
|
displayFields: [
|
|
8255
|
-
{ key: "
|
|
8256
|
-
{ key: "
|
|
8257
|
-
{ key: "end", label: "End" },
|
|
8258
|
-
{ key: "attendees", label: "Attendees" }
|
|
9737
|
+
{ key: "issueId", label: "Issue" },
|
|
9738
|
+
{ key: "labelId", label: "Label" }
|
|
8259
9739
|
]
|
|
8260
9740
|
},
|
|
8261
|
-
"
|
|
9741
|
+
"linear.issue.removeLabel": {
|
|
8262
9742
|
summaryTemplate: (p) => {
|
|
8263
9743
|
const parts = [];
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
["projectKey", "project"],
|
|
8267
|
-
"project",
|
|
8268
|
-
(v) => typeof v === "string" ? v : v?.key
|
|
8269
|
-
);
|
|
8270
|
-
const summary = jiraField(p, ["summary"], "summary");
|
|
8271
|
-
if (projectKey) parts.push(`${projectKey}:`);
|
|
8272
|
-
if (summary) parts.push(summary);
|
|
9744
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9745
|
+
if (p.labelId) parts.push(`Remove label ${p.labelId}`);
|
|
8273
9746
|
return parts.join(" ");
|
|
8274
9747
|
},
|
|
8275
|
-
// AIDENTITY-54: nested `fields.X` 形式と top-level canonical の両方を
|
|
8276
|
-
// 拾えるよう extract を使う。assignee は null (unassign) も表示。
|
|
8277
|
-
// legacy alias (project / issuetype 等) も top-level 候補に含めて後方互換を保つ。
|
|
8278
9748
|
displayFields: [
|
|
8279
|
-
{
|
|
8280
|
-
|
|
8281
|
-
extract: (p) => jiraField(
|
|
8282
|
-
p,
|
|
8283
|
-
["projectKey", "project"],
|
|
8284
|
-
"project",
|
|
8285
|
-
(v) => typeof v === "string" ? v : v?.key
|
|
8286
|
-
)
|
|
8287
|
-
},
|
|
8288
|
-
{
|
|
8289
|
-
label: "Type",
|
|
8290
|
-
extract: (p) => jiraField(
|
|
8291
|
-
p,
|
|
8292
|
-
["issueTypeName", "issueType", "issuetype"],
|
|
8293
|
-
"issuetype",
|
|
8294
|
-
(v) => typeof v === "string" ? v : v?.name
|
|
8295
|
-
)
|
|
8296
|
-
},
|
|
8297
|
-
{ label: "Summary", extract: (p) => jiraField(p, ["summary"], "summary") },
|
|
8298
|
-
{ label: "Description", extract: (p) => jiraField(p, ["description"], "description") },
|
|
8299
|
-
{
|
|
8300
|
-
label: "Priority",
|
|
8301
|
-
extract: (p) => jiraField(
|
|
8302
|
-
p,
|
|
8303
|
-
["priority"],
|
|
8304
|
-
"priority",
|
|
8305
|
-
(v) => typeof v === "string" ? v : v?.name
|
|
8306
|
-
)
|
|
8307
|
-
},
|
|
8308
|
-
{ label: "Assignee", extract: extractJiraAssigneeDisplay },
|
|
8309
|
-
{ label: "Labels", extract: (p) => jiraField(p, ["labels"], "labels") }
|
|
9749
|
+
{ key: "issueId", label: "Issue" },
|
|
9750
|
+
{ key: "labelId", label: "Label" }
|
|
8310
9751
|
]
|
|
8311
9752
|
},
|
|
8312
|
-
"
|
|
9753
|
+
"linear.issue.subscribe": {
|
|
8313
9754
|
summaryTemplate: (p) => {
|
|
8314
9755
|
const parts = [];
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
if (key) parts.push(`${key}:`);
|
|
8318
|
-
if (summary) parts.push(summary);
|
|
9756
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9757
|
+
parts.push("Subscribe");
|
|
8319
9758
|
return parts.join(" ");
|
|
8320
9759
|
},
|
|
8321
9760
|
displayFields: [
|
|
8322
|
-
|
|
8323
|
-
{ label: "Issue", extract: (p) => p.issueIdOrKey ?? p.issueKey },
|
|
8324
|
-
{ label: "Summary", extract: (p) => jiraField(p, ["summary"], "summary") },
|
|
8325
|
-
{ label: "Description", extract: (p) => jiraField(p, ["description"], "description") },
|
|
8326
|
-
{
|
|
8327
|
-
label: "Priority",
|
|
8328
|
-
extract: (p) => jiraField(
|
|
8329
|
-
p,
|
|
8330
|
-
["priority"],
|
|
8331
|
-
"priority",
|
|
8332
|
-
(v) => typeof v === "string" ? v : v?.name
|
|
8333
|
-
)
|
|
8334
|
-
},
|
|
8335
|
-
// AIDENTITY-54: top-level alias (string / object) と null (unassign) も解決。
|
|
8336
|
-
{ label: "Assignee", extract: extractJiraAssigneeDisplay },
|
|
8337
|
-
{ label: "Labels", extract: (p) => jiraField(p, ["labels"], "labels") }
|
|
9761
|
+
{ key: "issueId", label: "Issue" }
|
|
8338
9762
|
]
|
|
8339
9763
|
},
|
|
8340
|
-
|
|
8341
|
-
// detail 表示の ADF 描画は formatValueFull 側に任せて key 指定で OK。
|
|
8342
|
-
"jira.comment.create": {
|
|
9764
|
+
"linear.issue.delete": {
|
|
8343
9765
|
summaryTemplate: (p) => {
|
|
8344
9766
|
const parts = [];
|
|
8345
|
-
if (p.
|
|
8346
|
-
if (p.body) parts.push(typeof p.body === "string" ? p.body : "[ADF]");
|
|
9767
|
+
if (p.issueId) parts.push(`Delete issue ${p.issueId}`);
|
|
8347
9768
|
return parts.join(" ");
|
|
8348
9769
|
},
|
|
8349
9770
|
displayFields: [
|
|
8350
|
-
{ key: "
|
|
8351
|
-
{ key: "body", label: "Comment" }
|
|
9771
|
+
{ key: "issueId", label: "Issue" }
|
|
8352
9772
|
]
|
|
8353
9773
|
},
|
|
8354
|
-
//
|
|
8355
|
-
|
|
8356
|
-
"jira.comment.delete": {
|
|
9774
|
+
// ─── Linear Issue Relations ───
|
|
9775
|
+
"linear.issueRelation.create": {
|
|
8357
9776
|
summaryTemplate: (p) => {
|
|
8358
|
-
const
|
|
8359
|
-
|
|
8360
|
-
if (
|
|
8361
|
-
if (
|
|
8362
|
-
return "";
|
|
9777
|
+
const parts = [];
|
|
9778
|
+
if (p.issueId) parts.push(`${p.issueId}`);
|
|
9779
|
+
if (p.type) parts.push(String(p.type));
|
|
9780
|
+
if (p.relatedIssueId) parts.push(String(p.relatedIssueId));
|
|
9781
|
+
return parts.join(" ");
|
|
8363
9782
|
},
|
|
8364
9783
|
displayFields: [
|
|
8365
|
-
{
|
|
8366
|
-
{
|
|
9784
|
+
{ key: "issueId", label: "Issue" },
|
|
9785
|
+
{ key: "type", label: "Relation Type" },
|
|
9786
|
+
{ key: "relatedIssueId", label: "Related Issue" }
|
|
8367
9787
|
]
|
|
8368
9788
|
},
|
|
8369
|
-
|
|
8370
|
-
"jira.issuelink.delete": {
|
|
9789
|
+
"linear.issueRelation.list": {
|
|
8371
9790
|
summaryTemplate: (p) => {
|
|
8372
9791
|
const parts = [];
|
|
8373
|
-
if (p.
|
|
9792
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9793
|
+
parts.push("List relations");
|
|
8374
9794
|
return parts.join(" ");
|
|
8375
9795
|
},
|
|
8376
9796
|
displayFields: [
|
|
8377
|
-
{ key: "
|
|
9797
|
+
{ key: "issueId", label: "Issue" }
|
|
9798
|
+
]
|
|
9799
|
+
},
|
|
9800
|
+
"linear.issueRelation.delete": {
|
|
9801
|
+
summaryTemplate: (p) => {
|
|
9802
|
+
const parts = [];
|
|
9803
|
+
if (p.relationId) parts.push(`Delete relation ${p.relationId}`);
|
|
9804
|
+
return parts.join(" ");
|
|
9805
|
+
},
|
|
9806
|
+
displayFields: [
|
|
9807
|
+
{ key: "relationId", label: "Relation" }
|
|
9808
|
+
]
|
|
9809
|
+
},
|
|
9810
|
+
// ─── Linear Cycles ───
|
|
9811
|
+
"linear.cycle.list": {
|
|
9812
|
+
summaryTemplate: (p) => {
|
|
9813
|
+
const parts = [];
|
|
9814
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9815
|
+
parts.push("List cycles");
|
|
9816
|
+
return parts.join(" ");
|
|
9817
|
+
},
|
|
9818
|
+
displayFields: [
|
|
9819
|
+
{ key: "teamId", label: "Team" },
|
|
9820
|
+
{ key: "limit", label: "Limit" }
|
|
9821
|
+
]
|
|
9822
|
+
},
|
|
9823
|
+
"linear.cycle.read": {
|
|
9824
|
+
summaryTemplate: (p) => {
|
|
9825
|
+
const parts = [];
|
|
9826
|
+
if (p.cycleId) parts.push(`${p.cycleId}:`);
|
|
9827
|
+
parts.push("Read cycle");
|
|
9828
|
+
return parts.join(" ");
|
|
9829
|
+
},
|
|
9830
|
+
displayFields: [
|
|
9831
|
+
{ key: "cycleId", label: "Cycle" }
|
|
9832
|
+
]
|
|
9833
|
+
},
|
|
9834
|
+
"linear.cycle.create": {
|
|
9835
|
+
summaryTemplate: (p) => {
|
|
9836
|
+
const parts = [];
|
|
9837
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9838
|
+
if (p.name) parts.push(String(p.name));
|
|
9839
|
+
else if (p.startsAt) parts.push(`Cycle ${p.startsAt}`);
|
|
9840
|
+
return parts.join(" ");
|
|
9841
|
+
},
|
|
9842
|
+
displayFields: [
|
|
9843
|
+
{ key: "teamId", label: "Team" },
|
|
9844
|
+
{ key: "name", label: "Name" },
|
|
9845
|
+
{ key: "startsAt", label: "Starts At" },
|
|
9846
|
+
{ key: "endsAt", label: "Ends At" }
|
|
9847
|
+
]
|
|
9848
|
+
},
|
|
9849
|
+
"linear.cycle.update": {
|
|
9850
|
+
summaryTemplate: (p) => {
|
|
9851
|
+
const parts = [];
|
|
9852
|
+
if (p.cycleId) parts.push(`${p.cycleId}:`);
|
|
9853
|
+
if (p.name) parts.push(String(p.name));
|
|
9854
|
+
else parts.push("Update cycle");
|
|
9855
|
+
return parts.join(" ");
|
|
9856
|
+
},
|
|
9857
|
+
displayFields: [
|
|
9858
|
+
{ key: "cycleId", label: "Cycle" },
|
|
9859
|
+
{ key: "name", label: "Name" },
|
|
9860
|
+
{ key: "startsAt", label: "Starts At" },
|
|
9861
|
+
{ key: "endsAt", label: "Ends At" }
|
|
9862
|
+
]
|
|
9863
|
+
},
|
|
9864
|
+
// ─── Linear Labels ───
|
|
9865
|
+
"linear.label.create": {
|
|
9866
|
+
summaryTemplate: (p) => {
|
|
9867
|
+
const parts = [];
|
|
9868
|
+
if (p.name) parts.push(String(p.name));
|
|
9869
|
+
return parts.join(" ");
|
|
9870
|
+
},
|
|
9871
|
+
displayFields: [
|
|
9872
|
+
{ key: "name", label: "Name" },
|
|
9873
|
+
{ key: "color", label: "Color" },
|
|
9874
|
+
{ key: "teamId", label: "Team" }
|
|
9875
|
+
]
|
|
9876
|
+
},
|
|
9877
|
+
"linear.label.update": {
|
|
9878
|
+
summaryTemplate: (p) => {
|
|
9879
|
+
const parts = [];
|
|
9880
|
+
if (p.labelId) parts.push(`${p.labelId}:`);
|
|
9881
|
+
if (p.name) parts.push(String(p.name));
|
|
9882
|
+
else parts.push("Update label");
|
|
9883
|
+
return parts.join(" ");
|
|
9884
|
+
},
|
|
9885
|
+
displayFields: [
|
|
9886
|
+
{ key: "labelId", label: "Label" },
|
|
9887
|
+
{ key: "name", label: "Name" },
|
|
9888
|
+
{ key: "color", label: "Color" }
|
|
9889
|
+
]
|
|
9890
|
+
},
|
|
9891
|
+
// ─── Linear Attachments ───
|
|
9892
|
+
"linear.attachment.create": {
|
|
9893
|
+
summaryTemplate: (p) => {
|
|
9894
|
+
const parts = [];
|
|
9895
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9896
|
+
if (p.title) parts.push(String(p.title));
|
|
9897
|
+
return parts.join(" ");
|
|
9898
|
+
},
|
|
9899
|
+
displayFields: [
|
|
9900
|
+
{ key: "issueId", label: "Issue" },
|
|
9901
|
+
{ key: "title", label: "Title" },
|
|
9902
|
+
{ key: "url", label: "URL" }
|
|
9903
|
+
]
|
|
9904
|
+
},
|
|
9905
|
+
"linear.attachment.list": {
|
|
9906
|
+
summaryTemplate: (p) => {
|
|
9907
|
+
const parts = [];
|
|
9908
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9909
|
+
parts.push("List attachments");
|
|
9910
|
+
return parts.join(" ");
|
|
9911
|
+
},
|
|
9912
|
+
displayFields: [
|
|
9913
|
+
{ key: "issueId", label: "Issue" }
|
|
9914
|
+
]
|
|
9915
|
+
},
|
|
9916
|
+
"linear.attachment.delete": {
|
|
9917
|
+
summaryTemplate: (p) => {
|
|
9918
|
+
const parts = [];
|
|
9919
|
+
if (p.attachmentId) parts.push(`Delete attachment ${p.attachmentId}`);
|
|
9920
|
+
return parts.join(" ");
|
|
9921
|
+
},
|
|
9922
|
+
displayFields: [
|
|
9923
|
+
{ key: "attachmentId", label: "Attachment" }
|
|
9924
|
+
]
|
|
9925
|
+
},
|
|
9926
|
+
// ─── Linear read actions (登録漏れ補完) ───
|
|
9927
|
+
"linear.issue.list": {
|
|
9928
|
+
summaryTemplate: (p) => {
|
|
9929
|
+
const parts = [];
|
|
9930
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9931
|
+
parts.push("List issues");
|
|
9932
|
+
return parts.join(" ");
|
|
9933
|
+
},
|
|
9934
|
+
displayFields: [
|
|
9935
|
+
{ key: "teamId", label: "Team" },
|
|
9936
|
+
{ key: "assigneeId", label: "Assignee" },
|
|
9937
|
+
{ key: "stateId", label: "State" },
|
|
9938
|
+
{ key: "limit", label: "Limit" }
|
|
9939
|
+
]
|
|
9940
|
+
},
|
|
9941
|
+
"linear.issue.read": {
|
|
9942
|
+
summaryTemplate: (p) => {
|
|
9943
|
+
const parts = [];
|
|
9944
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9945
|
+
parts.push("Read issue");
|
|
9946
|
+
return parts.join(" ");
|
|
9947
|
+
},
|
|
9948
|
+
displayFields: [
|
|
9949
|
+
{ key: "issueId", label: "Issue" }
|
|
9950
|
+
]
|
|
9951
|
+
},
|
|
9952
|
+
"linear.issue.search": {
|
|
9953
|
+
summaryTemplate: (p) => {
|
|
9954
|
+
const parts = [];
|
|
9955
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9956
|
+
if (p.query) parts.push(String(p.query));
|
|
9957
|
+
return parts.join(" ");
|
|
9958
|
+
},
|
|
9959
|
+
displayFields: [
|
|
9960
|
+
{ key: "query", label: "Query" },
|
|
9961
|
+
{ key: "teamId", label: "Team" },
|
|
9962
|
+
{ key: "limit", label: "Limit" }
|
|
9963
|
+
]
|
|
9964
|
+
},
|
|
9965
|
+
"linear.comment.list": {
|
|
9966
|
+
summaryTemplate: (p) => {
|
|
9967
|
+
const parts = [];
|
|
9968
|
+
if (p.issueId) parts.push(`${p.issueId}:`);
|
|
9969
|
+
parts.push("List comments");
|
|
9970
|
+
return parts.join(" ");
|
|
9971
|
+
},
|
|
9972
|
+
displayFields: [
|
|
9973
|
+
{ key: "issueId", label: "Issue" }
|
|
9974
|
+
]
|
|
9975
|
+
},
|
|
9976
|
+
"linear.project.list": {
|
|
9977
|
+
summaryTemplate: (p) => {
|
|
9978
|
+
const parts = [];
|
|
9979
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
9980
|
+
parts.push("List projects");
|
|
9981
|
+
return parts.join(" ");
|
|
9982
|
+
},
|
|
9983
|
+
displayFields: [
|
|
9984
|
+
{ key: "teamId", label: "Team" },
|
|
9985
|
+
{ key: "limit", label: "Limit" }
|
|
9986
|
+
]
|
|
9987
|
+
},
|
|
9988
|
+
"linear.project.read": {
|
|
9989
|
+
summaryTemplate: (p) => {
|
|
9990
|
+
const parts = [];
|
|
9991
|
+
if (p.projectId) parts.push(`${p.projectId}:`);
|
|
9992
|
+
parts.push("Read project");
|
|
9993
|
+
return parts.join(" ");
|
|
9994
|
+
},
|
|
9995
|
+
displayFields: [
|
|
9996
|
+
{ key: "projectId", label: "Project" }
|
|
9997
|
+
]
|
|
9998
|
+
},
|
|
9999
|
+
"linear.team.list": {
|
|
10000
|
+
summaryTemplate: (_p) => "List teams",
|
|
10001
|
+
displayFields: [
|
|
10002
|
+
{ key: "limit", label: "Limit" }
|
|
10003
|
+
]
|
|
10004
|
+
},
|
|
10005
|
+
"linear.workflowState.list": {
|
|
10006
|
+
summaryTemplate: (p) => {
|
|
10007
|
+
const parts = [];
|
|
10008
|
+
if (p.teamId) parts.push(`${p.teamId}:`);
|
|
10009
|
+
parts.push("List workflow states");
|
|
10010
|
+
return parts.join(" ");
|
|
10011
|
+
},
|
|
10012
|
+
displayFields: [
|
|
10013
|
+
{ key: "teamId", label: "Team" },
|
|
10014
|
+
{ key: "limit", label: "Limit" }
|
|
8378
10015
|
]
|
|
8379
10016
|
},
|
|
10017
|
+
"linear.viewer.read": {
|
|
10018
|
+
summaryTemplate: (_p) => "Read viewer (current user)",
|
|
10019
|
+
displayFields: []
|
|
10020
|
+
},
|
|
8380
10021
|
// AIDENTITY-83: email / displayName から accountId を解決する read action。
|
|
8381
10022
|
"jira.user.search": {
|
|
8382
10023
|
summaryTemplate: (p) => {
|
|
@@ -8399,7 +10040,8 @@ var ACTION_DISPLAY_CONFIGS = {
|
|
|
8399
10040
|
displayFields: [
|
|
8400
10041
|
{ key: "to", label: "To" },
|
|
8401
10042
|
{ key: "taskType", label: "Task" },
|
|
8402
|
-
{ key: "message", label: "Message" }
|
|
10043
|
+
{ key: "message", label: "Message" },
|
|
10044
|
+
{ key: "payload", label: "Payload" }
|
|
8403
10045
|
]
|
|
8404
10046
|
},
|
|
8405
10047
|
"inbox.respond": {
|
|
@@ -8427,15 +10069,25 @@ var ACTION_DISPLAY_CONFIGS = {
|
|
|
8427
10069
|
]
|
|
8428
10070
|
},
|
|
8429
10071
|
"inbox.checkByToken": {
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
]
|
|
10072
|
+
// token is an opaque access credential — never render it in summaries or display fields.
|
|
10073
|
+
summaryTemplate: (_p) => "Check inbox by token",
|
|
10074
|
+
displayFields: []
|
|
8434
10075
|
},
|
|
8435
10076
|
"inbox.complete": {
|
|
8436
10077
|
summaryTemplate: (p) => p.id ? `Complete #${p.id}` : "",
|
|
8437
10078
|
displayFields: [
|
|
8438
|
-
{ key: "id", label: "Item" }
|
|
10079
|
+
{ key: "id", label: "Item" },
|
|
10080
|
+
{ key: "result", label: "Result" }
|
|
10081
|
+
]
|
|
10082
|
+
},
|
|
10083
|
+
"scheduling.request": {
|
|
10084
|
+
summaryTemplate: (p) => p.topic ? `Request scheduling: ${p.topic}` : "Request scheduling",
|
|
10085
|
+
displayFields: [
|
|
10086
|
+
{ key: "to", label: "To" },
|
|
10087
|
+
{ key: "topic", label: "Topic" },
|
|
10088
|
+
{ key: "durationMinutes", label: "Duration (min)" },
|
|
10089
|
+
{ key: "candidates", label: "Candidates" },
|
|
10090
|
+
{ key: "message", label: "Message" }
|
|
8439
10091
|
]
|
|
8440
10092
|
}
|
|
8441
10093
|
};
|
|
@@ -8743,7 +10395,7 @@ function isWriteAction(action) {
|
|
|
8743
10395
|
if (!meta) {
|
|
8744
10396
|
return true;
|
|
8745
10397
|
}
|
|
8746
|
-
const writeEffectPrefixes = ["Create:", "Update:", "Delete:", "Write:", "Execute:", "Merge:", "Run:"];
|
|
10398
|
+
const writeEffectPrefixes = ["Create:", "Update:", "Delete:", "Write:", "Execute:", "Merge:", "Run:", "Archive:"];
|
|
8747
10399
|
if (meta.effects?.some((e) => writeEffectPrefixes.some((p) => e.startsWith(p)))) {
|
|
8748
10400
|
return true;
|
|
8749
10401
|
}
|