@render-harness/cap-linear 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # `@render-harness/cap-linear`
2
+
3
+ Linear webhook and issue tools for agents in the Render harness.
4
+
5
+ Use this pack when an agent should react to Linear webhook events, inspect issue context, and optionally create or update Linear issues.
6
+
7
+ ## Configuration
8
+
9
+ Drop the pack into `render-harness.yaml`:
10
+
11
+ ```yaml
12
+ capabilities:
13
+ - pack: "@render-harness/cap-linear"
14
+ config:
15
+ webhookSecretEnv: "LINEAR_WEBHOOK_SECRET"
16
+ apiKeyEnv: "LINEAR_API_KEY"
17
+ accessMode: "read"
18
+ ```
19
+
20
+ Set these environment variables on the entry that loads the agent:
21
+
22
+ - `LINEAR_WEBHOOK_SECRET`: Linear webhook signing secret used to verify events.
23
+ - `LINEAR_API_KEY`: Linear API key used for reads and optional write tools.
24
+
25
+ ## Connector
26
+
27
+ The pack mounts the `linear` connector at `/connectors/linear`. Configure that URL as a Linear webhook endpoint and use the same secret as `LINEAR_WEBHOOK_SECRET`.
28
+
29
+ Each accepted Linear webhook event enqueues one harness run.
30
+
31
+ ## Config Keys
32
+
33
+ | Key | Type | Default | Notes |
34
+ | --- | --- | --- | --- |
35
+ | `agent` | string | default agent | Agent name to enqueue runs for. |
36
+ | `userId` | string | `cap-linear` | User ID stored on enqueued runs. |
37
+ | `webhookSecretEnv` | string | `LINEAR_WEBHOOK_SECRET` | Env var that contains the Linear webhook secret. |
38
+ | `apiKeyEnv` | string | `LINEAR_API_KEY` | Env var that contains the Linear API key. |
39
+ | `accessMode` | `read` or `read_write` | `read` | Enables write tools only when set to `read_write`. |
40
+ | `allowedTeams` | string[] | all teams | Restricts events to matching team IDs or team keys. |
41
+ | `allowedProjects` | string[] | all projects | Restricts events to matching project IDs or project names. |
42
+ | `states` | string[] | all states | Restricts issue events to matching workflow state names. |
43
+ | `labels` | string[] | all labels | Restricts issue events to matching label names. |
44
+ | `ignoredActors` | string[] | none | Ignores events from matching Linear actor IDs. |
45
+
46
+ ## Tools
47
+
48
+ Read tools are available when `LINEAR_API_KEY` is set:
49
+
50
+ - `linear.get_issue`
51
+ - `linear.search_issues`
52
+ - `linear.list_comments`
53
+ - `linear.list_teams`
54
+ - `linear.list_projects`
55
+ - `linear.list_workflow_states`
56
+ - `linear.list_users`
57
+
58
+ Set `accessMode: read_write` to enable write tools:
59
+
60
+ - `linear.create_issue`
61
+ - `linear.create_comment`
62
+ - `linear.update_issue`
63
+ - `linear.update_issue_status`
64
+ - `linear.assign_issue`
65
+ - `linear.link_related_issue`
66
+
67
+ Use `permissions.requireApproval` for write tools if the agent should ask before mutating Linear state.
68
+
69
+ ## Test Commands
70
+
71
+ ```sh
72
+ pnpm --filter @render-harness/cap-linear build
73
+ pnpm --filter @render-harness/cap-linear test
74
+ ```
package/dist/index.js CHANGED
@@ -5,6 +5,10 @@ import { LinearWebhookClient } from '@linear/sdk/webhooks';
5
5
 
6
6
  // src/index.ts
7
7
 
8
+ // package.json
9
+ var package_default = {
10
+ version: "0.2.2"};
11
+
8
12
  // src/normalize.ts
9
13
  function normalizeLinearEvent(body, cfg = {}) {
10
14
  if (!body || typeof body !== "object") return null;
@@ -441,7 +445,7 @@ var DEFAULT_WEBHOOK_SECRET_ENV = "LINEAR_WEBHOOK_SECRET";
441
445
  var DEFAULT_API_KEY_ENV = "LINEAR_API_KEY";
442
446
  var pack = definePack({
443
447
  name: "cap-linear",
444
- version: "0.1.0",
448
+ version: package_default.version,
445
449
  envSchema: [
446
450
  {
447
451
  name: DEFAULT_WEBHOOK_SECRET_ENV,
@@ -459,7 +463,7 @@ var pack = definePack({
459
463
  localTools(ctx) {
460
464
  const cfg = readConfig(ctx.config);
461
465
  const apiKey = ctx.env(cfg.apiKeyEnv);
462
- if (!apiKey) throw new Error(`cap-linear: ${cfg.apiKeyEnv} is not set`);
466
+ if (!apiKey) return [];
463
467
  return linearTools({ apiKey, accessMode: cfg.accessMode });
464
468
  },
465
469
  connectors(ctx) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/normalize.ts","../src/tools.ts","../src/verify.ts","../src/index.ts"],"names":["stringValue","stringAt"],"mappings":"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","file":"index.js","sourcesContent":["export interface LinearFilterConfig {\n allowedTeams?: string[];\n allowedProjects?: string[];\n states?: string[];\n labels?: string[];\n ignoredActors?: string[];\n}\n\nexport interface NormalizedLinearEvent {\n type: string;\n action?: string;\n organizationId?: string;\n teamId?: string;\n teamKey?: string;\n projectId?: string;\n issueId?: string;\n issueIdentifier?: string;\n state?: string;\n actorId?: string;\n url?: string;\n summary: string;\n}\n\nexport function normalizeLinearEvent(\n body: unknown,\n cfg: LinearFilterConfig = {},\n): NormalizedLinearEvent | null {\n if (!body || typeof body !== \"object\") return null;\n const payload = body as Record<string, unknown>;\n const type = stringValue(payload.type);\n if (!type) return null;\n const action = stringValue(payload.action);\n const data = objectValue(payload.data);\n if (!data) return null;\n\n const actorId = stringAt(payload, \"actor.id\") ?? stringAt(payload, \"actorId\");\n if (actorId && cfg.ignoredActors?.includes(actorId)) return null;\n const teamId = stringAt(data, \"team.id\") ?? stringAt(data, \"teamId\");\n const teamKey = stringAt(data, \"team.key\");\n if (cfg.allowedTeams?.length && !matchesAny([teamId, teamKey], cfg.allowedTeams)) return null;\n const projectId = stringAt(data, \"project.id\") ?? stringAt(data, \"projectId\");\n const projectName = stringAt(data, \"project.name\");\n if (cfg.allowedProjects?.length && !matchesAny([projectId, projectName], cfg.allowedProjects)) {\n return null;\n }\n const state = stringAt(data, \"state.name\") ?? stringAt(data, \"state\");\n if (cfg.states?.length && state && !cfg.states.includes(state)) return null;\n if (cfg.labels?.length && !hasAllowedLabel(data, cfg.labels)) return null;\n\n const issueId = stringValue(data.id);\n const issueIdentifier = stringValue(data.identifier);\n const organizationId = stringValue(payload.organizationId);\n const url = stringValue(data.url);\n return {\n type,\n ...(action ? { action } : {}),\n ...(organizationId ? { organizationId } : {}),\n ...(teamId ? { teamId } : {}),\n ...(teamKey ? { teamKey } : {}),\n ...(projectId ? { projectId } : {}),\n ...(issueId ? { issueId } : {}),\n ...(issueIdentifier ? { issueIdentifier } : {}),\n ...(state ? { state } : {}),\n ...(actorId ? { actorId } : {}),\n ...(url ? { url } : {}),\n summary: `Linear ${type}${issueIdentifier ? ` ${issueIdentifier}` : \"\"} ${action ?? \"changed\"}`,\n };\n}\n\nfunction hasAllowedLabel(data: Record<string, unknown>, allowed: string[]): boolean {\n const labels = arrayValue(data.labels)\n .map((label) =>\n label && typeof label === \"object\" ? stringValue((label as { name?: unknown }).name) : null,\n )\n .filter((label): label is string => !!label);\n return labels.some((label) => allowed.includes(label));\n}\n\nfunction matchesAny(values: Array<string | undefined>, allowed: string[]): boolean {\n return values.some((value) => value !== undefined && allowed.includes(value));\n}\n\nfunction stringAt(value: unknown, path: string): string | undefined {\n let cursor = value;\n for (const part of path.split(\".\")) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return stringValue(cursor);\n}\n\nfunction objectValue(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction arrayValue(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n","import { LinearClient } from \"@linear/sdk\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\n\nexport type LinearAccessMode = \"read\" | \"read_write\";\n\nexport function linearTools(args: {\n apiKey: string;\n accessMode: LinearAccessMode;\n}): LocalToolHandler[] {\n const client = new LinearClient({ apiKey: args.apiKey });\n const tools: LocalToolHandler[] = [\n jsonTool(\n \"linear.get_issue\",\n \"Read a Linear issue by id.\",\n idSchema(\"issueId\"),\n async (input) => {\n const { issueId } = input as { issueId: string };\n return client.client.request(\n `query Issue($id: String!) {\n issue(id: $id) {\n id\n identifier\n title\n description\n url\n state { id name }\n team { id key name }\n project { id name }\n assignee { id name email }\n labels { nodes { id name } }\n }\n }`,\n { id: issueId },\n );\n },\n ),\n jsonTool(\n \"linear.search_issues\",\n \"Search Linear issues with a text query.\",\n objectSchema({ query: { type: \"string\" } }),\n async (input) => {\n const { query } = input as { query: string };\n return client.client.request(\n `query SearchIssues($query: String!) {\n issueSearch(query: $query) {\n nodes {\n id\n identifier\n title\n url\n state { name }\n team { key name }\n }\n }\n }`,\n { query },\n );\n },\n ),\n jsonTool(\n \"linear.list_comments\",\n \"List comments for a Linear issue.\",\n idSchema(\"issueId\"),\n async (input) => {\n const { issueId } = input as { issueId: string };\n return client.client.request(\n `query IssueComments($id: String!) {\n issue(id: $id) {\n comments {\n nodes {\n id\n body\n createdAt\n user { id name email }\n }\n }\n }\n }`,\n { id: issueId },\n );\n },\n ),\n jsonTool(\"linear.list_teams\", \"List Linear teams.\", emptySchema(), async () =>\n client.client.request(\n `query Teams {\n teams {\n nodes {\n id\n key\n name\n }\n }\n }`,\n ),\n ),\n jsonTool(\"linear.list_projects\", \"List Linear projects.\", emptySchema(), async () =>\n client.client.request(\n `query Projects {\n projects {\n nodes {\n id\n name\n url\n state\n teams { nodes { id key name } }\n }\n }\n }`,\n ),\n ),\n jsonTool(\n \"linear.list_workflow_states\",\n \"List Linear workflow states, optionally scoped to a team.\",\n objectSchema({ teamId: { type: \"string\", optional: true } }),\n async (input) => {\n const { teamId } = input as { teamId?: string };\n return client.client.request(\n `query WorkflowStates($filter: WorkflowStateFilter) {\n workflowStates(filter: $filter) {\n nodes {\n id\n name\n type\n team { id key name }\n }\n }\n }`,\n { filter: teamId ? { team: { id: { eq: teamId } } } : undefined },\n );\n },\n ),\n jsonTool(\"linear.list_users\", \"List Linear users.\", emptySchema(), async () =>\n client.client.request(\n `query Users {\n users {\n nodes {\n id\n name\n email\n active\n }\n }\n }`,\n ),\n ),\n ];\n\n if (args.accessMode === \"read_write\") {\n tools.push(\n jsonTool(\n \"linear.create_issue\",\n \"Create a Linear issue.\",\n createIssueSchema(),\n async (input) => {\n const { teamId, title, description, assigneeId, projectId, cycleId, stateId, priority } =\n input as CreateIssueInput;\n return client.client.request(\n `mutation IssueCreate($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue { id identifier title url }\n }\n }`,\n {\n input: {\n teamId,\n title,\n ...(description ? { description } : {}),\n ...(assigneeId ? { assigneeId } : {}),\n ...(projectId ? { projectId } : {}),\n ...(cycleId ? { cycleId } : {}),\n ...(stateId ? { stateId } : {}),\n ...(priority !== undefined ? { priority } : {}),\n },\n },\n );\n },\n ),\n jsonTool(\n \"linear.create_comment\",\n \"Create a comment on a Linear issue.\",\n objectSchema({ issueId: { type: \"string\" }, body: { type: \"string\" } }),\n async (input) => {\n const { issueId, body } = input as { issueId: string; body: string };\n return client.client.request(\n `mutation CommentCreate($input: CommentCreateInput!) {\n commentCreate(input: $input) {\n success\n comment { id url body }\n }\n }`,\n { input: { issueId, body } },\n );\n },\n ),\n jsonTool(\n \"linear.update_issue\",\n \"Update Linear issue fields.\",\n updateIssueSchema(),\n async (input) => {\n const {\n issueId,\n title,\n description,\n stateId,\n assigneeId,\n projectId,\n cycleId,\n priority,\n labelIds,\n } = input as UpdateIssueInput;\n return client.client.request(\n `mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue {\n id\n identifier\n title\n state { id name }\n assignee { id name }\n project { id name }\n cycle { id name }\n }\n }\n }`,\n {\n id: issueId,\n input: {\n ...(title ? { title } : {}),\n ...(description ? { description } : {}),\n ...(stateId ? { stateId } : {}),\n ...(assigneeId ? { assigneeId } : {}),\n ...(projectId ? { projectId } : {}),\n ...(cycleId ? { cycleId } : {}),\n ...(priority !== undefined ? { priority } : {}),\n ...(labelIds ? { labelIds } : {}),\n },\n },\n );\n },\n ),\n jsonTool(\n \"linear.update_issue_status\",\n \"Update a Linear issue's status.\",\n objectSchema({ issueId: { type: \"string\" }, stateId: { type: \"string\" } }),\n async (input) => {\n const { issueId, stateId } = input as { issueId: string; stateId: string };\n return client.client.request(\n `mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue { id identifier state { id name } }\n }\n }`,\n { id: issueId, input: { stateId } },\n );\n },\n ),\n jsonTool(\n \"linear.assign_issue\",\n \"Assign a Linear issue to a user.\",\n objectSchema({ issueId: { type: \"string\" }, assigneeId: { type: \"string\" } }),\n async (input) => {\n const { issueId, assigneeId } = input as { issueId: string; assigneeId: string };\n return client.client.request(\n `mutation IssueAssign($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue { id identifier assignee { id name } }\n }\n }`,\n { id: issueId, input: { assigneeId } },\n );\n },\n ),\n jsonTool(\n \"linear.link_related_issue\",\n \"Create a Linear issue relation between two issues.\",\n objectSchema({\n issueId: { type: \"string\" },\n relatedIssueId: { type: \"string\" },\n type: { type: \"string\" },\n }),\n async (input) => {\n const { issueId, relatedIssueId, type } = input as {\n issueId: string;\n relatedIssueId: string;\n type: string;\n };\n return client.client.request(\n `mutation IssueRelationCreate($input: IssueRelationCreateInput!) {\n issueRelationCreate(input: $input) {\n success\n issueRelation { id type }\n }\n }`,\n { input: { issueId, relatedIssueId, type } },\n );\n },\n ),\n );\n }\n\n return tools;\n}\n\nfunction jsonTool(\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n call: (input: unknown) => Promise<unknown>,\n): LocalToolHandler {\n return {\n definition: { name, description, inputSchema, source: \"pack:cap-linear\" },\n handler: async ({ input }) => {\n try {\n return { content: JSON.stringify(await call(input), null, 2) };\n } catch (err) {\n return { content: err instanceof Error ? err.message : String(err), isError: true };\n }\n },\n };\n}\n\ninterface CreateIssueInput {\n teamId: string;\n title: string;\n description?: string;\n assigneeId?: string;\n projectId?: string;\n cycleId?: string;\n stateId?: string;\n priority?: number;\n}\n\ninterface UpdateIssueInput {\n issueId: string;\n title?: string;\n description?: string;\n stateId?: string;\n assigneeId?: string;\n projectId?: string;\n cycleId?: string;\n priority?: number;\n labelIds?: string[];\n}\n\nfunction emptySchema() {\n return objectSchema({});\n}\n\nfunction idSchema(name: string) {\n return objectSchema({ [name]: { type: \"string\" } });\n}\n\nfunction createIssueSchema() {\n return objectSchema({\n teamId: { type: \"string\" },\n title: { type: \"string\" },\n description: { type: \"string\", optional: true },\n assigneeId: { type: \"string\", optional: true },\n projectId: { type: \"string\", optional: true },\n cycleId: { type: \"string\", optional: true },\n stateId: { type: \"string\", optional: true },\n priority: { type: \"number\", optional: true },\n });\n}\n\nfunction updateIssueSchema() {\n return objectSchema({\n issueId: { type: \"string\" },\n title: { type: \"string\", optional: true },\n description: { type: \"string\", optional: true },\n stateId: { type: \"string\", optional: true },\n assigneeId: { type: \"string\", optional: true },\n projectId: { type: \"string\", optional: true },\n cycleId: { type: \"string\", optional: true },\n priority: { type: \"number\", optional: true },\n labelIds: { type: \"array\", items: { type: \"string\" }, optional: true },\n });\n}\n\nfunction objectSchema(properties: Record<string, unknown>) {\n return {\n type: \"object\",\n additionalProperties: false,\n properties,\n required: Object.entries(properties)\n .filter(([, value]) => !(value as { optional?: boolean }).optional)\n .map(([key]) => key),\n };\n}\n","import { LinearWebhookClient } from \"@linear/sdk/webhooks\";\n\nexport function verifyLinearWebhook(args: {\n rawBody: string;\n signature: string | null;\n secret: string;\n timestamp?: number;\n}): boolean {\n if (!args.signature) return false;\n try {\n return new LinearWebhookClient(args.secret).verify(\n Buffer.from(args.rawBody),\n args.signature,\n args.timestamp,\n );\n } catch {\n return false;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\nimport { type ConnectorContribution, definePack, type PackContext } from \"@render-harness/registry\";\nimport { type LinearFilterConfig, normalizeLinearEvent } from \"./normalize.js\";\nimport { type LinearAccessMode, linearTools } from \"./tools.js\";\nimport { verifyLinearWebhook } from \"./verify.js\";\n\ninterface LinearConfig extends LinearFilterConfig {\n agent?: string;\n userId?: string;\n webhookSecretEnv?: string;\n apiKeyEnv?: string;\n accessMode?: LinearAccessMode;\n}\n\nconst DEFAULT_WEBHOOK_SECRET_ENV = \"LINEAR_WEBHOOK_SECRET\";\nconst DEFAULT_API_KEY_ENV = \"LINEAR_API_KEY\";\n\nconst pack = definePack({\n name: \"cap-linear\",\n version: \"0.1.0\",\n envSchema: [\n {\n name: DEFAULT_WEBHOOK_SECRET_ENV,\n required: true,\n secret: true,\n description: \"Linear webhook signing secret.\",\n },\n {\n name: DEFAULT_API_KEY_ENV,\n required: true,\n secret: true,\n description: \"Linear API key used for read tools and optional write tools.\",\n },\n ],\n localTools(ctx: PackContext): LocalToolHandler[] {\n const cfg = readConfig(ctx.config);\n const apiKey = ctx.env(cfg.apiKeyEnv);\n if (!apiKey) throw new Error(`cap-linear: ${cfg.apiKeyEnv} is not set`);\n return linearTools({ apiKey, accessMode: cfg.accessMode });\n },\n connectors(ctx: PackContext): ConnectorContribution[] {\n const cfg = readConfig(ctx.config);\n return [\n {\n key: \"linear\",\n webhook: async (req, webCtx) => {\n const rawBody = await req.text();\n const parsed = parseBody(rawBody);\n const secret = ctx.env(cfg.webhookSecretEnv);\n if (!secret) return json({ error: \"missing_secret\", env: cfg.webhookSecretEnv }, 500);\n const verifyArgs = {\n rawBody,\n secret,\n signature: req.headers.get(\"linear-signature\"),\n };\n const timestamp = timestampFrom(parsed);\n if (\n !verifyLinearWebhook({\n ...verifyArgs,\n ...(timestamp !== undefined ? { timestamp } : {}),\n })\n ) {\n return json({ error: \"invalid_signature\" }, 401);\n }\n\n const normalized = normalizeLinearEvent(parsed, cfg);\n if (!normalized) return json({ ok: true, skipped: true });\n const agent = webCtx.resolveAgent(cfg.agent);\n const runId = `linear-${hash(deliverySeed(parsed, rawBody))}`;\n const result = await webCtx.enqueueRun({\n agentName: agent.name,\n agentVersion: agent.version,\n userId: cfg.userId ?? \"cap-linear\",\n runId,\n initialContent: [{ type: \"text\", text: normalized.summary }],\n metadata: { connector: \"cap-linear\", ...normalized },\n });\n return json(result, result.status === \"enqueued\" ? 202 : 200);\n },\n },\n ];\n },\n});\n\nexport default pack;\n\ntype ResolvedLinearConfig = Required<\n Pick<LinearConfig, \"webhookSecretEnv\" | \"apiKeyEnv\" | \"accessMode\">\n> &\n Omit<LinearConfig, \"webhookSecretEnv\" | \"apiKeyEnv\" | \"accessMode\">;\n\nfunction readConfig(raw: Record<string, unknown>): ResolvedLinearConfig {\n const cfg: ResolvedLinearConfig = {\n webhookSecretEnv: stringValue(raw.webhookSecretEnv) ?? DEFAULT_WEBHOOK_SECRET_ENV,\n apiKeyEnv: stringValue(raw.apiKeyEnv) ?? DEFAULT_API_KEY_ENV,\n accessMode: raw.accessMode === \"read_write\" ? \"read_write\" : \"read\",\n };\n const agent = stringValue(raw.agent);\n if (agent) cfg.agent = agent;\n const userId = stringValue(raw.userId);\n if (userId) cfg.userId = userId;\n const allowedTeams = stringArray(raw.allowedTeams);\n if (allowedTeams) cfg.allowedTeams = allowedTeams;\n const allowedProjects = stringArray(raw.allowedProjects);\n if (allowedProjects) cfg.allowedProjects = allowedProjects;\n const states = stringArray(raw.states);\n if (states) cfg.states = states;\n const labels = stringArray(raw.labels);\n if (labels) cfg.labels = labels;\n const ignoredActors = stringArray(raw.ignoredActors);\n if (ignoredActors) cfg.ignoredActors = ignoredActors;\n return cfg;\n}\n\nfunction parseBody(rawBody: string): unknown {\n try {\n return JSON.parse(rawBody);\n } catch {\n return null;\n }\n}\n\nfunction timestampFrom(value: unknown): number | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const found = (value as Record<string, unknown>).webhookTimestamp;\n return typeof found === \"number\" ? found : undefined;\n}\n\nfunction deliverySeed(value: unknown, rawBody: string): string {\n if (!value || typeof value !== \"object\") return rawBody;\n const payload = value as Record<string, unknown>;\n return [\n stringValue(payload.organizationId),\n stringValue(payload.type),\n stringValue(payload.action),\n stringAt(payload, \"data.id\"),\n stringAt(payload, \"data.updatedAt\"),\n stringAt(payload, \"data.createdAt\"),\n ]\n .filter(Boolean)\n .join(\":\");\n}\n\nfunction stringAt(value: unknown, path: string): string | undefined {\n let cursor = value;\n for (const part of path.split(\".\")) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return stringValue(cursor);\n}\n\nfunction hash(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 32);\n}\n\nfunction json(body: unknown, status = 200): Response {\n return Response.json(body, { status });\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : undefined;\n}\n"]}
1
+ {"version":3,"sources":["../package.json","../src/normalize.ts","../src/tools.ts","../src/verify.ts","../src/index.ts"],"names":["stringValue","stringAt"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"name\": \"@render-harness/cap-linear\",\n \"version\": \"0.2.2\",\n \"description\": \"Linear monitoring capability pack for the Render agent harness.\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"keywords\": [\n \"render-harness-cap\",\n \"render-harness\",\n \"linear\"\n ],\n \"renderHarness\": {\n \"gallery\": {\n \"label\": \"Linear\",\n \"envHint\": \"LINEAR_API_KEY\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\"\n },\n \"dependencies\": {\n \"@linear/sdk\": \"^63.4.0\",\n \"@render-harness/registry\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@render-harness/core\": \"workspace:*\",\n \"@types/node\": \"^25.6.2\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.5\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","export interface LinearFilterConfig {\n allowedTeams?: string[];\n allowedProjects?: string[];\n states?: string[];\n labels?: string[];\n ignoredActors?: string[];\n}\n\nexport interface NormalizedLinearEvent {\n type: string;\n action?: string;\n organizationId?: string;\n teamId?: string;\n teamKey?: string;\n projectId?: string;\n issueId?: string;\n issueIdentifier?: string;\n state?: string;\n actorId?: string;\n url?: string;\n summary: string;\n}\n\nexport function normalizeLinearEvent(\n body: unknown,\n cfg: LinearFilterConfig = {},\n): NormalizedLinearEvent | null {\n if (!body || typeof body !== \"object\") return null;\n const payload = body as Record<string, unknown>;\n const type = stringValue(payload.type);\n if (!type) return null;\n const action = stringValue(payload.action);\n const data = objectValue(payload.data);\n if (!data) return null;\n\n const actorId = stringAt(payload, \"actor.id\") ?? stringAt(payload, \"actorId\");\n if (actorId && cfg.ignoredActors?.includes(actorId)) return null;\n const teamId = stringAt(data, \"team.id\") ?? stringAt(data, \"teamId\");\n const teamKey = stringAt(data, \"team.key\");\n if (cfg.allowedTeams?.length && !matchesAny([teamId, teamKey], cfg.allowedTeams)) return null;\n const projectId = stringAt(data, \"project.id\") ?? stringAt(data, \"projectId\");\n const projectName = stringAt(data, \"project.name\");\n if (cfg.allowedProjects?.length && !matchesAny([projectId, projectName], cfg.allowedProjects)) {\n return null;\n }\n const state = stringAt(data, \"state.name\") ?? stringAt(data, \"state\");\n if (cfg.states?.length && state && !cfg.states.includes(state)) return null;\n if (cfg.labels?.length && !hasAllowedLabel(data, cfg.labels)) return null;\n\n const issueId = stringValue(data.id);\n const issueIdentifier = stringValue(data.identifier);\n const organizationId = stringValue(payload.organizationId);\n const url = stringValue(data.url);\n return {\n type,\n ...(action ? { action } : {}),\n ...(organizationId ? { organizationId } : {}),\n ...(teamId ? { teamId } : {}),\n ...(teamKey ? { teamKey } : {}),\n ...(projectId ? { projectId } : {}),\n ...(issueId ? { issueId } : {}),\n ...(issueIdentifier ? { issueIdentifier } : {}),\n ...(state ? { state } : {}),\n ...(actorId ? { actorId } : {}),\n ...(url ? { url } : {}),\n summary: `Linear ${type}${issueIdentifier ? ` ${issueIdentifier}` : \"\"} ${action ?? \"changed\"}`,\n };\n}\n\nfunction hasAllowedLabel(data: Record<string, unknown>, allowed: string[]): boolean {\n const labels = arrayValue(data.labels)\n .map((label) =>\n label && typeof label === \"object\" ? stringValue((label as { name?: unknown }).name) : null,\n )\n .filter((label): label is string => !!label);\n return labels.some((label) => allowed.includes(label));\n}\n\nfunction matchesAny(values: Array<string | undefined>, allowed: string[]): boolean {\n return values.some((value) => value !== undefined && allowed.includes(value));\n}\n\nfunction stringAt(value: unknown, path: string): string | undefined {\n let cursor = value;\n for (const part of path.split(\".\")) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return stringValue(cursor);\n}\n\nfunction objectValue(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction arrayValue(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n","import { LinearClient } from \"@linear/sdk\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\n\nexport type LinearAccessMode = \"read\" | \"read_write\";\n\nexport function linearTools(args: {\n apiKey: string;\n accessMode: LinearAccessMode;\n}): LocalToolHandler[] {\n const client = new LinearClient({ apiKey: args.apiKey });\n const tools: LocalToolHandler[] = [\n jsonTool(\n \"linear.get_issue\",\n \"Read a Linear issue by id.\",\n idSchema(\"issueId\"),\n async (input) => {\n const { issueId } = input as { issueId: string };\n return client.client.request(\n `query Issue($id: String!) {\n issue(id: $id) {\n id\n identifier\n title\n description\n url\n state { id name }\n team { id key name }\n project { id name }\n assignee { id name email }\n labels { nodes { id name } }\n }\n }`,\n { id: issueId },\n );\n },\n ),\n jsonTool(\n \"linear.search_issues\",\n \"Search Linear issues with a text query.\",\n objectSchema({ query: { type: \"string\" } }),\n async (input) => {\n const { query } = input as { query: string };\n return client.client.request(\n `query SearchIssues($query: String!) {\n issueSearch(query: $query) {\n nodes {\n id\n identifier\n title\n url\n state { name }\n team { key name }\n }\n }\n }`,\n { query },\n );\n },\n ),\n jsonTool(\n \"linear.list_comments\",\n \"List comments for a Linear issue.\",\n idSchema(\"issueId\"),\n async (input) => {\n const { issueId } = input as { issueId: string };\n return client.client.request(\n `query IssueComments($id: String!) {\n issue(id: $id) {\n comments {\n nodes {\n id\n body\n createdAt\n user { id name email }\n }\n }\n }\n }`,\n { id: issueId },\n );\n },\n ),\n jsonTool(\"linear.list_teams\", \"List Linear teams.\", emptySchema(), async () =>\n client.client.request(\n `query Teams {\n teams {\n nodes {\n id\n key\n name\n }\n }\n }`,\n ),\n ),\n jsonTool(\"linear.list_projects\", \"List Linear projects.\", emptySchema(), async () =>\n client.client.request(\n `query Projects {\n projects {\n nodes {\n id\n name\n url\n state\n teams { nodes { id key name } }\n }\n }\n }`,\n ),\n ),\n jsonTool(\n \"linear.list_workflow_states\",\n \"List Linear workflow states, optionally scoped to a team.\",\n objectSchema({ teamId: { type: \"string\", optional: true } }),\n async (input) => {\n const { teamId } = input as { teamId?: string };\n return client.client.request(\n `query WorkflowStates($filter: WorkflowStateFilter) {\n workflowStates(filter: $filter) {\n nodes {\n id\n name\n type\n team { id key name }\n }\n }\n }`,\n { filter: teamId ? { team: { id: { eq: teamId } } } : undefined },\n );\n },\n ),\n jsonTool(\"linear.list_users\", \"List Linear users.\", emptySchema(), async () =>\n client.client.request(\n `query Users {\n users {\n nodes {\n id\n name\n email\n active\n }\n }\n }`,\n ),\n ),\n ];\n\n if (args.accessMode === \"read_write\") {\n tools.push(\n jsonTool(\n \"linear.create_issue\",\n \"Create a Linear issue.\",\n createIssueSchema(),\n async (input) => {\n const { teamId, title, description, assigneeId, projectId, cycleId, stateId, priority } =\n input as CreateIssueInput;\n return client.client.request(\n `mutation IssueCreate($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue { id identifier title url }\n }\n }`,\n {\n input: {\n teamId,\n title,\n ...(description ? { description } : {}),\n ...(assigneeId ? { assigneeId } : {}),\n ...(projectId ? { projectId } : {}),\n ...(cycleId ? { cycleId } : {}),\n ...(stateId ? { stateId } : {}),\n ...(priority !== undefined ? { priority } : {}),\n },\n },\n );\n },\n ),\n jsonTool(\n \"linear.create_comment\",\n \"Create a comment on a Linear issue.\",\n objectSchema({ issueId: { type: \"string\" }, body: { type: \"string\" } }),\n async (input) => {\n const { issueId, body } = input as { issueId: string; body: string };\n return client.client.request(\n `mutation CommentCreate($input: CommentCreateInput!) {\n commentCreate(input: $input) {\n success\n comment { id url body }\n }\n }`,\n { input: { issueId, body } },\n );\n },\n ),\n jsonTool(\n \"linear.update_issue\",\n \"Update Linear issue fields.\",\n updateIssueSchema(),\n async (input) => {\n const {\n issueId,\n title,\n description,\n stateId,\n assigneeId,\n projectId,\n cycleId,\n priority,\n labelIds,\n } = input as UpdateIssueInput;\n return client.client.request(\n `mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue {\n id\n identifier\n title\n state { id name }\n assignee { id name }\n project { id name }\n cycle { id name }\n }\n }\n }`,\n {\n id: issueId,\n input: {\n ...(title ? { title } : {}),\n ...(description ? { description } : {}),\n ...(stateId ? { stateId } : {}),\n ...(assigneeId ? { assigneeId } : {}),\n ...(projectId ? { projectId } : {}),\n ...(cycleId ? { cycleId } : {}),\n ...(priority !== undefined ? { priority } : {}),\n ...(labelIds ? { labelIds } : {}),\n },\n },\n );\n },\n ),\n jsonTool(\n \"linear.update_issue_status\",\n \"Update a Linear issue's status.\",\n objectSchema({ issueId: { type: \"string\" }, stateId: { type: \"string\" } }),\n async (input) => {\n const { issueId, stateId } = input as { issueId: string; stateId: string };\n return client.client.request(\n `mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue { id identifier state { id name } }\n }\n }`,\n { id: issueId, input: { stateId } },\n );\n },\n ),\n jsonTool(\n \"linear.assign_issue\",\n \"Assign a Linear issue to a user.\",\n objectSchema({ issueId: { type: \"string\" }, assigneeId: { type: \"string\" } }),\n async (input) => {\n const { issueId, assigneeId } = input as { issueId: string; assigneeId: string };\n return client.client.request(\n `mutation IssueAssign($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue { id identifier assignee { id name } }\n }\n }`,\n { id: issueId, input: { assigneeId } },\n );\n },\n ),\n jsonTool(\n \"linear.link_related_issue\",\n \"Create a Linear issue relation between two issues.\",\n objectSchema({\n issueId: { type: \"string\" },\n relatedIssueId: { type: \"string\" },\n type: { type: \"string\" },\n }),\n async (input) => {\n const { issueId, relatedIssueId, type } = input as {\n issueId: string;\n relatedIssueId: string;\n type: string;\n };\n return client.client.request(\n `mutation IssueRelationCreate($input: IssueRelationCreateInput!) {\n issueRelationCreate(input: $input) {\n success\n issueRelation { id type }\n }\n }`,\n { input: { issueId, relatedIssueId, type } },\n );\n },\n ),\n );\n }\n\n return tools;\n}\n\nfunction jsonTool(\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n call: (input: unknown) => Promise<unknown>,\n): LocalToolHandler {\n return {\n definition: { name, description, inputSchema, source: \"pack:cap-linear\" },\n handler: async ({ input }) => {\n try {\n return { content: JSON.stringify(await call(input), null, 2) };\n } catch (err) {\n return { content: err instanceof Error ? err.message : String(err), isError: true };\n }\n },\n };\n}\n\ninterface CreateIssueInput {\n teamId: string;\n title: string;\n description?: string;\n assigneeId?: string;\n projectId?: string;\n cycleId?: string;\n stateId?: string;\n priority?: number;\n}\n\ninterface UpdateIssueInput {\n issueId: string;\n title?: string;\n description?: string;\n stateId?: string;\n assigneeId?: string;\n projectId?: string;\n cycleId?: string;\n priority?: number;\n labelIds?: string[];\n}\n\nfunction emptySchema() {\n return objectSchema({});\n}\n\nfunction idSchema(name: string) {\n return objectSchema({ [name]: { type: \"string\" } });\n}\n\nfunction createIssueSchema() {\n return objectSchema({\n teamId: { type: \"string\" },\n title: { type: \"string\" },\n description: { type: \"string\", optional: true },\n assigneeId: { type: \"string\", optional: true },\n projectId: { type: \"string\", optional: true },\n cycleId: { type: \"string\", optional: true },\n stateId: { type: \"string\", optional: true },\n priority: { type: \"number\", optional: true },\n });\n}\n\nfunction updateIssueSchema() {\n return objectSchema({\n issueId: { type: \"string\" },\n title: { type: \"string\", optional: true },\n description: { type: \"string\", optional: true },\n stateId: { type: \"string\", optional: true },\n assigneeId: { type: \"string\", optional: true },\n projectId: { type: \"string\", optional: true },\n cycleId: { type: \"string\", optional: true },\n priority: { type: \"number\", optional: true },\n labelIds: { type: \"array\", items: { type: \"string\" }, optional: true },\n });\n}\n\nfunction objectSchema(properties: Record<string, unknown>) {\n return {\n type: \"object\",\n additionalProperties: false,\n properties,\n required: Object.entries(properties)\n .filter(([, value]) => !(value as { optional?: boolean }).optional)\n .map(([key]) => key),\n };\n}\n","import { LinearWebhookClient } from \"@linear/sdk/webhooks\";\n\nexport function verifyLinearWebhook(args: {\n rawBody: string;\n signature: string | null;\n secret: string;\n timestamp?: number;\n}): boolean {\n if (!args.signature) return false;\n try {\n return new LinearWebhookClient(args.secret).verify(\n Buffer.from(args.rawBody),\n args.signature,\n args.timestamp,\n );\n } catch {\n return false;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\nimport { type ConnectorContribution, definePack, type PackContext } from \"@render-harness/registry\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { type LinearFilterConfig, normalizeLinearEvent } from \"./normalize.js\";\nimport { type LinearAccessMode, linearTools } from \"./tools.js\";\nimport { verifyLinearWebhook } from \"./verify.js\";\n\ninterface LinearConfig extends LinearFilterConfig {\n agent?: string;\n userId?: string;\n webhookSecretEnv?: string;\n apiKeyEnv?: string;\n accessMode?: LinearAccessMode;\n}\n\nconst DEFAULT_WEBHOOK_SECRET_ENV = \"LINEAR_WEBHOOK_SECRET\";\nconst DEFAULT_API_KEY_ENV = \"LINEAR_API_KEY\";\n\nconst pack = definePack({\n name: \"cap-linear\",\n version: pkg.version,\n envSchema: [\n {\n name: DEFAULT_WEBHOOK_SECRET_ENV,\n required: true,\n secret: true,\n description: \"Linear webhook signing secret.\",\n },\n {\n name: DEFAULT_API_KEY_ENV,\n required: true,\n secret: true,\n description: \"Linear API key used for read tools and optional write tools.\",\n },\n ],\n localTools(ctx: PackContext): LocalToolHandler[] {\n const cfg = readConfig(ctx.config);\n const apiKey = ctx.env(cfg.apiKeyEnv);\n if (!apiKey) return [];\n return linearTools({ apiKey, accessMode: cfg.accessMode });\n },\n connectors(ctx: PackContext): ConnectorContribution[] {\n const cfg = readConfig(ctx.config);\n return [\n {\n key: \"linear\",\n webhook: async (req, webCtx) => {\n const rawBody = await req.text();\n const parsed = parseBody(rawBody);\n const secret = ctx.env(cfg.webhookSecretEnv);\n if (!secret) return json({ error: \"missing_secret\", env: cfg.webhookSecretEnv }, 500);\n const verifyArgs = {\n rawBody,\n secret,\n signature: req.headers.get(\"linear-signature\"),\n };\n const timestamp = timestampFrom(parsed);\n if (\n !verifyLinearWebhook({\n ...verifyArgs,\n ...(timestamp !== undefined ? { timestamp } : {}),\n })\n ) {\n return json({ error: \"invalid_signature\" }, 401);\n }\n\n const normalized = normalizeLinearEvent(parsed, cfg);\n if (!normalized) return json({ ok: true, skipped: true });\n const agent = webCtx.resolveAgent(cfg.agent);\n const runId = `linear-${hash(deliverySeed(parsed, rawBody))}`;\n const result = await webCtx.enqueueRun({\n agentName: agent.name,\n agentVersion: agent.version,\n userId: cfg.userId ?? \"cap-linear\",\n runId,\n initialContent: [{ type: \"text\", text: normalized.summary }],\n metadata: { connector: \"cap-linear\", ...normalized },\n });\n return json(result, result.status === \"enqueued\" ? 202 : 200);\n },\n },\n ];\n },\n});\n\nexport default pack;\n\ntype ResolvedLinearConfig = Required<\n Pick<LinearConfig, \"webhookSecretEnv\" | \"apiKeyEnv\" | \"accessMode\">\n> &\n Omit<LinearConfig, \"webhookSecretEnv\" | \"apiKeyEnv\" | \"accessMode\">;\n\nfunction readConfig(raw: Record<string, unknown>): ResolvedLinearConfig {\n const cfg: ResolvedLinearConfig = {\n webhookSecretEnv: stringValue(raw.webhookSecretEnv) ?? DEFAULT_WEBHOOK_SECRET_ENV,\n apiKeyEnv: stringValue(raw.apiKeyEnv) ?? DEFAULT_API_KEY_ENV,\n accessMode: raw.accessMode === \"read_write\" ? \"read_write\" : \"read\",\n };\n const agent = stringValue(raw.agent);\n if (agent) cfg.agent = agent;\n const userId = stringValue(raw.userId);\n if (userId) cfg.userId = userId;\n const allowedTeams = stringArray(raw.allowedTeams);\n if (allowedTeams) cfg.allowedTeams = allowedTeams;\n const allowedProjects = stringArray(raw.allowedProjects);\n if (allowedProjects) cfg.allowedProjects = allowedProjects;\n const states = stringArray(raw.states);\n if (states) cfg.states = states;\n const labels = stringArray(raw.labels);\n if (labels) cfg.labels = labels;\n const ignoredActors = stringArray(raw.ignoredActors);\n if (ignoredActors) cfg.ignoredActors = ignoredActors;\n return cfg;\n}\n\nfunction parseBody(rawBody: string): unknown {\n try {\n return JSON.parse(rawBody);\n } catch {\n return null;\n }\n}\n\nfunction timestampFrom(value: unknown): number | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const found = (value as Record<string, unknown>).webhookTimestamp;\n return typeof found === \"number\" ? found : undefined;\n}\n\nfunction deliverySeed(value: unknown, rawBody: string): string {\n if (!value || typeof value !== \"object\") return rawBody;\n const payload = value as Record<string, unknown>;\n return [\n stringValue(payload.organizationId),\n stringValue(payload.type),\n stringValue(payload.action),\n stringAt(payload, \"data.id\"),\n stringAt(payload, \"data.updatedAt\"),\n stringAt(payload, \"data.createdAt\"),\n ]\n .filter(Boolean)\n .join(\":\");\n}\n\nfunction stringAt(value: unknown, path: string): string | undefined {\n let cursor = value;\n for (const part of path.split(\".\")) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return stringValue(cursor);\n}\n\nfunction hash(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 32);\n}\n\nfunction json(body: unknown, status = 200): Response {\n return Response.json(body, { status });\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : undefined;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@render-harness/cap-linear",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Linear monitoring capability pack for the Render agent harness.",
5
5
  "type": "module",
6
6
  "license": "MIT",