@shipfox/api-integration-linear 8.0.0 → 9.0.1

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.
Files changed (58) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +30 -0
  3. package/dist/core/agent-tools-provider.d.ts +2 -2
  4. package/dist/core/agent-tools-provider.d.ts.map +1 -1
  5. package/dist/core/agent-tools-provider.js.map +1 -1
  6. package/dist/core/agent-tools.d.ts +1 -1
  7. package/dist/core/agent-tools.d.ts.map +1 -1
  8. package/dist/core/agent-tools.js.map +1 -1
  9. package/dist/core/errors.d.ts +1 -1
  10. package/dist/core/errors.d.ts.map +1 -1
  11. package/dist/core/errors.js +1 -1
  12. package/dist/core/errors.js.map +1 -1
  13. package/dist/core/install.d.ts +1 -1
  14. package/dist/core/install.d.ts.map +1 -1
  15. package/dist/core/install.js.map +1 -1
  16. package/dist/core/webhook-processor.d.ts +1 -1
  17. package/dist/core/webhook-processor.d.ts.map +1 -1
  18. package/dist/core/webhook-processor.js +1 -1
  19. package/dist/core/webhook-processor.js.map +1 -1
  20. package/dist/core/webhook.d.ts +1 -1
  21. package/dist/core/webhook.d.ts.map +1 -1
  22. package/dist/core/webhook.js.map +1 -1
  23. package/dist/presentation/dto/integrations.d.ts +4 -5
  24. package/dist/presentation/dto/integrations.d.ts.map +1 -1
  25. package/dist/presentation/dto/integrations.js +15 -2
  26. package/dist/presentation/dto/integrations.js.map +1 -1
  27. package/dist/presentation/e2eRoutes/create-connection.d.ts +1 -1
  28. package/dist/presentation/e2eRoutes/create-connection.d.ts.map +1 -1
  29. package/dist/presentation/e2eRoutes/create-connection.js.map +1 -1
  30. package/dist/presentation/routes/errors.js +1 -1
  31. package/dist/presentation/routes/errors.js.map +1 -1
  32. package/dist/presentation/routes/install.d.ts +1 -1
  33. package/dist/presentation/routes/install.d.ts.map +1 -1
  34. package/dist/presentation/routes/install.js.map +1 -1
  35. package/dist/presentation/routes/webhooks.d.ts +1 -1
  36. package/dist/presentation/routes/webhooks.d.ts.map +1 -1
  37. package/dist/presentation/routes/webhooks.js +1 -1
  38. package/dist/presentation/routes/webhooks.js.map +1 -1
  39. package/dist/tsconfig.test.tsbuildinfo +1 -1
  40. package/package.json +12 -13
  41. package/src/core/agent-tools-provider.test.ts +1 -1
  42. package/src/core/agent-tools-provider.ts +1 -1
  43. package/src/core/agent-tools.ts +1 -1
  44. package/src/core/errors.ts +1 -1
  45. package/src/core/install.ts +1 -1
  46. package/src/core/webhook-processor.test.ts +2 -2
  47. package/src/core/webhook-processor.ts +5 -5
  48. package/src/core/webhook.test.ts +2 -2
  49. package/src/core/webhook.ts +6 -6
  50. package/src/presentation/dto/integrations.ts +20 -3
  51. package/src/presentation/e2eRoutes/create-connection.ts +1 -1
  52. package/src/presentation/e2eRoutes/index.test.ts +1 -1
  53. package/src/presentation/routes/errors.ts +1 -1
  54. package/src/presentation/routes/install.test.ts +1 -1
  55. package/src/presentation/routes/install.ts +1 -1
  56. package/src/presentation/routes/webhooks.test.ts +2 -2
  57. package/src/presentation/routes/webhooks.ts +2 -5
  58. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 24 files with swc (527.98ms)
2
+ Successfully compiled: 24 files with swc (327.98ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @shipfox/api-integration-linear
2
2
 
3
+ ## 9.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 475ce59: Republishes all public packages after restoring release authorization.
8
+ - Updated dependencies [475ce59]
9
+ - @shipfox/api-auth-context@9.0.1
10
+ - @shipfox/api-integration-linear-dto@9.0.1
11
+ - @shipfox/api-integration-spi@0.2.1
12
+ - @shipfox/config@1.2.3
13
+ - @shipfox/node-drizzle@0.3.3
14
+ - @shipfox/node-fastify@0.3.1
15
+ - @shipfox/node-opentelemetry@0.6.1
16
+ - @shipfox/node-postgres@0.4.3
17
+
18
+ ## 9.0.0
19
+
20
+ ### Patch Changes
21
+
22
+ - 4a6d124: Separates Integrations provider SPI contracts from the public DTO surface.
23
+ - Updated dependencies [4a6d124]
24
+ - @shipfox/api-integration-spi@0.2.0
25
+ - @shipfox/api-auth-context@9.0.0
26
+ - @shipfox/api-integration-linear-dto@9.0.0
27
+ - @shipfox/config@1.2.2
28
+ - @shipfox/node-drizzle@0.3.2
29
+ - @shipfox/node-fastify@0.3.0
30
+ - @shipfox/node-opentelemetry@0.6.0
31
+ - @shipfox/node-postgres@0.4.2
32
+
3
33
  ## 8.0.0
4
34
 
5
35
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
- import type { AgentToolCallInput, AgentToolSession, AgentToolsProvider, IntegrationConnection, OpenAgentToolsSessionInput } from '@shipfox/api-integration-core-dto';
2
+ import type { AgentToolCallInput, AgentToolSession, AgentToolsProvider, IntegrationConnection, OpenAgentToolsSessionInput } from '@shipfox/api-integration-spi';
3
3
  import { type LinearAgentToolRequiredScope } from '#core/agent-tools.js';
4
4
  import type { LinearTokenStore } from '#core/tokens.js';
5
5
  type LinearIntegrationConnection = IntegrationConnection<'linear'>;
@@ -25,7 +25,7 @@ export declare class LinearAgentToolsProvider implements AgentToolsProvider<Line
25
25
  private readonly createClient;
26
26
  constructor(options: LinearAgentToolsProviderOptions);
27
27
  catalog(): readonly [import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry, import("#core/agent-tools.js").LinearAgentToolCatalogEntry];
28
- selectionCatalog(): import("@shipfox/api-integration-core-dto").AgentToolSelectionCatalog;
28
+ selectionCatalog(): import("@shipfox/api-integration-spi").AgentToolSelectionCatalog;
29
29
  openSession(input: OpenAgentToolsSessionInput<LinearIntegrationConnection, LinearAgentToolRequiredScope>): Promise<AgentToolSession<CallToolResult>>;
30
30
  }
31
31
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tools-provider.d.ts","sourceRoot":"","sources":["../../src/core/agent-tools-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,cAAc,EAAuB,MAAM,oCAAoC,CAAC;AAC7F,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,KAAK,4BAA4B,EAGlC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAKtD,KAAK,2BAA2B,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAEnE,UAAU,eAAe;IACvB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAChF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,2BAA2B;IACnC,QAAQ,EAAE,GAAG,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,2BAA2B,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAE/F,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,YAAY,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAClD;AAED,qBAAa,wBACX,YAAW,kBAAkB,CAAC,2BAA2B,EAAE,4BAA4B,CAAC;IAM5E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;gBAExB,OAAO,EAAE,+BAA+B;IAMrE,OAAO;IAIP,gBAAgB;IAIV,WAAW,CACf,KAAK,EAAE,0BAA0B,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,GAC3F,OAAO,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CAW7C"}
1
+ {"version":3,"file":"agent-tools-provider.d.ts","sourceRoot":"","sources":["../../src/core/agent-tools-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,cAAc,EAAuB,MAAM,oCAAoC,CAAC;AAC7F,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,4BAA4B,EAGlC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAKtD,KAAK,2BAA2B,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAEnE,UAAU,eAAe;IACvB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAChF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,2BAA2B;IACnC,QAAQ,EAAE,GAAG,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,2BAA2B,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAE/F,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,YAAY,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAClD;AAED,qBAAa,wBACX,YAAW,kBAAkB,CAAC,2BAA2B,EAAE,4BAA4B,CAAC;IAM5E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;gBAExB,OAAO,EAAE,+BAA+B;IAMrE,OAAO;IAIP,gBAAgB;IAIV,WAAW,CACf,KAAK,EAAE,0BAA0B,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,GAC3F,OAAO,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CAW7C"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/agent-tools-provider.ts"],"sourcesContent":["import {Client} from '@modelcontextprotocol/sdk/client/index.js';\nimport {StreamableHTTPClientTransport} from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {type CallToolResult, CallToolResultSchema} from '@modelcontextprotocol/sdk/types.js';\nimport type {\n AgentToolCallInput,\n AgentToolSession,\n AgentToolsProvider,\n IntegrationConnection,\n OpenAgentToolsSessionInput,\n} from '@shipfox/api-integration-core-dto';\nimport {\n type LinearAgentToolRequiredScope,\n linearAgentToolCatalog,\n linearAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\n\nconst LINEAR_MCP_ENDPOINT = 'https://mcp.linear.app/mcp';\nconst LINEAR_MCP_CALL_TIMEOUT_MS = 30_000;\n\ntype LinearIntegrationConnection = IntegrationConnection<'linear'>;\n\ninterface LinearMcpClient {\n callTool(input: AgentToolCallInput, timeoutMs: number): Promise<CallToolResult>;\n close(): Promise<void>;\n}\n\ninterface CreateLinearMcpClientParams {\n endpoint: URL;\n accessToken: string;\n}\n\ntype CreateLinearMcpClient = (params: CreateLinearMcpClientParams) => Promise<LinearMcpClient>;\n\nexport interface LinearAgentToolsProviderOptions {\n tokenStore: Pick<LinearTokenStore, 'getAccessToken'>;\n endpoint?: string | URL | undefined;\n callTimeoutMs?: number | undefined;\n createClient?: CreateLinearMcpClient | undefined;\n}\n\nexport class LinearAgentToolsProvider\n implements AgentToolsProvider<LinearIntegrationConnection, LinearAgentToolRequiredScope>\n{\n private readonly endpoint: URL;\n private readonly callTimeoutMs: number;\n private readonly createClient: CreateLinearMcpClient;\n\n constructor(private readonly options: LinearAgentToolsProviderOptions) {\n this.endpoint = new URL(options.endpoint ?? LINEAR_MCP_ENDPOINT);\n this.callTimeoutMs = options.callTimeoutMs ?? LINEAR_MCP_CALL_TIMEOUT_MS;\n this.createClient = options.createClient ?? createSdkLinearMcpClient;\n }\n\n catalog() {\n return linearAgentToolCatalog;\n }\n\n selectionCatalog() {\n return linearAgentToolSelectionCatalog;\n }\n\n async openSession(\n input: OpenAgentToolsSessionInput<LinearIntegrationConnection, LinearAgentToolRequiredScope>,\n ): Promise<AgentToolSession<CallToolResult>> {\n const accessToken = await this.options.tokenStore.getAccessToken({\n connectionId: input.connection.id,\n });\n const client = await this.createClient({endpoint: this.endpoint, accessToken});\n\n return {\n call: (call) => client.callTool(call, this.callTimeoutMs),\n close: () => client.close(),\n };\n }\n}\n\nasync function createSdkLinearMcpClient(\n params: CreateLinearMcpClientParams,\n): Promise<LinearMcpClient> {\n const client = new Client({name: 'shipfox-linear-tools', version: '0.0.0'});\n const transport = new StreamableHTTPClientTransport(params.endpoint, {\n requestInit: {\n headers: {authorization: `Bearer ${params.accessToken}`},\n },\n });\n\n await client.connect(transport as unknown as Transport);\n\n return {\n callTool: async (input, timeoutMs) => {\n const result = await client.callTool(\n {name: input.toolId, arguments: input.arguments},\n CallToolResultSchema,\n {\n timeout: timeoutMs,\n },\n );\n return result as CallToolResult;\n },\n close: async () => {\n await client.close();\n },\n };\n}\n"],"names":["Client","StreamableHTTPClientTransport","CallToolResultSchema","linearAgentToolCatalog","linearAgentToolSelectionCatalog","LINEAR_MCP_ENDPOINT","LINEAR_MCP_CALL_TIMEOUT_MS","LinearAgentToolsProvider","options","endpoint","URL","callTimeoutMs","createClient","createSdkLinearMcpClient","catalog","selectionCatalog","openSession","input","accessToken","tokenStore","getAccessToken","connectionId","connection","id","client","call","callTool","close","params","name","version","transport","requestInit","headers","authorization","connect","timeoutMs","result","toolId","arguments","timeout"],"mappings":"AAAA,SAAQA,MAAM,QAAO,4CAA4C;AACjE,SAAQC,6BAA6B,QAAO,qDAAqD;AAEjG,SAA6BC,oBAAoB,QAAO,qCAAqC;AAQ7F,SAEEC,sBAAsB,EACtBC,+BAA+B,QAC1B,uBAAuB;AAG9B,MAAMC,sBAAsB;AAC5B,MAAMC,6BAA6B;AAuBnC,OAAO,MAAMC;IAOX,YAAY,AAAiBC,OAAwC,CAAE;aAA1CA,UAAAA;QAC3B,IAAI,CAACC,QAAQ,GAAG,IAAIC,IAAIF,QAAQC,QAAQ,IAAIJ;QAC5C,IAAI,CAACM,aAAa,GAAGH,QAAQG,aAAa,IAAIL;QAC9C,IAAI,CAACM,YAAY,GAAGJ,QAAQI,YAAY,IAAIC;IAC9C;IAEAC,UAAU;QACR,OAAOX;IACT;IAEAY,mBAAmB;QACjB,OAAOX;IACT;IAEA,MAAMY,YACJC,KAA4F,EACjD;QAC3C,MAAMC,cAAc,MAAM,IAAI,CAACV,OAAO,CAACW,UAAU,CAACC,cAAc,CAAC;YAC/DC,cAAcJ,MAAMK,UAAU,CAACC,EAAE;QACnC;QACA,MAAMC,SAAS,MAAM,IAAI,CAACZ,YAAY,CAAC;YAACH,UAAU,IAAI,CAACA,QAAQ;YAAES;QAAW;QAE5E,OAAO;YACLO,MAAM,CAACA,OAASD,OAAOE,QAAQ,CAACD,MAAM,IAAI,CAACd,aAAa;YACxDgB,OAAO,IAAMH,OAAOG,KAAK;QAC3B;IACF;AACF;AAEA,eAAed,yBACbe,MAAmC;IAEnC,MAAMJ,SAAS,IAAIxB,OAAO;QAAC6B,MAAM;QAAwBC,SAAS;IAAO;IACzE,MAAMC,YAAY,IAAI9B,8BAA8B2B,OAAOnB,QAAQ,EAAE;QACnEuB,aAAa;YACXC,SAAS;gBAACC,eAAe,CAAC,OAAO,EAAEN,OAAOV,WAAW,EAAE;YAAA;QACzD;IACF;IAEA,MAAMM,OAAOW,OAAO,CAACJ;IAErB,OAAO;QACLL,UAAU,OAAOT,OAAOmB;YACtB,MAAMC,SAAS,MAAMb,OAAOE,QAAQ,CAClC;gBAACG,MAAMZ,MAAMqB,MAAM;gBAAEC,WAAWtB,MAAMsB,SAAS;YAAA,GAC/CrC,sBACA;gBACEsC,SAASJ;YACX;YAEF,OAAOC;QACT;QACAV,OAAO;YACL,MAAMH,OAAOG,KAAK;QACpB;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/core/agent-tools-provider.ts"],"sourcesContent":["import {Client} from '@modelcontextprotocol/sdk/client/index.js';\nimport {StreamableHTTPClientTransport} from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {type CallToolResult, CallToolResultSchema} from '@modelcontextprotocol/sdk/types.js';\nimport type {\n AgentToolCallInput,\n AgentToolSession,\n AgentToolsProvider,\n IntegrationConnection,\n OpenAgentToolsSessionInput,\n} from '@shipfox/api-integration-spi';\nimport {\n type LinearAgentToolRequiredScope,\n linearAgentToolCatalog,\n linearAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\n\nconst LINEAR_MCP_ENDPOINT = 'https://mcp.linear.app/mcp';\nconst LINEAR_MCP_CALL_TIMEOUT_MS = 30_000;\n\ntype LinearIntegrationConnection = IntegrationConnection<'linear'>;\n\ninterface LinearMcpClient {\n callTool(input: AgentToolCallInput, timeoutMs: number): Promise<CallToolResult>;\n close(): Promise<void>;\n}\n\ninterface CreateLinearMcpClientParams {\n endpoint: URL;\n accessToken: string;\n}\n\ntype CreateLinearMcpClient = (params: CreateLinearMcpClientParams) => Promise<LinearMcpClient>;\n\nexport interface LinearAgentToolsProviderOptions {\n tokenStore: Pick<LinearTokenStore, 'getAccessToken'>;\n endpoint?: string | URL | undefined;\n callTimeoutMs?: number | undefined;\n createClient?: CreateLinearMcpClient | undefined;\n}\n\nexport class LinearAgentToolsProvider\n implements AgentToolsProvider<LinearIntegrationConnection, LinearAgentToolRequiredScope>\n{\n private readonly endpoint: URL;\n private readonly callTimeoutMs: number;\n private readonly createClient: CreateLinearMcpClient;\n\n constructor(private readonly options: LinearAgentToolsProviderOptions) {\n this.endpoint = new URL(options.endpoint ?? LINEAR_MCP_ENDPOINT);\n this.callTimeoutMs = options.callTimeoutMs ?? LINEAR_MCP_CALL_TIMEOUT_MS;\n this.createClient = options.createClient ?? createSdkLinearMcpClient;\n }\n\n catalog() {\n return linearAgentToolCatalog;\n }\n\n selectionCatalog() {\n return linearAgentToolSelectionCatalog;\n }\n\n async openSession(\n input: OpenAgentToolsSessionInput<LinearIntegrationConnection, LinearAgentToolRequiredScope>,\n ): Promise<AgentToolSession<CallToolResult>> {\n const accessToken = await this.options.tokenStore.getAccessToken({\n connectionId: input.connection.id,\n });\n const client = await this.createClient({endpoint: this.endpoint, accessToken});\n\n return {\n call: (call) => client.callTool(call, this.callTimeoutMs),\n close: () => client.close(),\n };\n }\n}\n\nasync function createSdkLinearMcpClient(\n params: CreateLinearMcpClientParams,\n): Promise<LinearMcpClient> {\n const client = new Client({name: 'shipfox-linear-tools', version: '0.0.0'});\n const transport = new StreamableHTTPClientTransport(params.endpoint, {\n requestInit: {\n headers: {authorization: `Bearer ${params.accessToken}`},\n },\n });\n\n await client.connect(transport as unknown as Transport);\n\n return {\n callTool: async (input, timeoutMs) => {\n const result = await client.callTool(\n {name: input.toolId, arguments: input.arguments},\n CallToolResultSchema,\n {\n timeout: timeoutMs,\n },\n );\n return result as CallToolResult;\n },\n close: async () => {\n await client.close();\n },\n };\n}\n"],"names":["Client","StreamableHTTPClientTransport","CallToolResultSchema","linearAgentToolCatalog","linearAgentToolSelectionCatalog","LINEAR_MCP_ENDPOINT","LINEAR_MCP_CALL_TIMEOUT_MS","LinearAgentToolsProvider","options","endpoint","URL","callTimeoutMs","createClient","createSdkLinearMcpClient","catalog","selectionCatalog","openSession","input","accessToken","tokenStore","getAccessToken","connectionId","connection","id","client","call","callTool","close","params","name","version","transport","requestInit","headers","authorization","connect","timeoutMs","result","toolId","arguments","timeout"],"mappings":"AAAA,SAAQA,MAAM,QAAO,4CAA4C;AACjE,SAAQC,6BAA6B,QAAO,qDAAqD;AAEjG,SAA6BC,oBAAoB,QAAO,qCAAqC;AAQ7F,SAEEC,sBAAsB,EACtBC,+BAA+B,QAC1B,uBAAuB;AAG9B,MAAMC,sBAAsB;AAC5B,MAAMC,6BAA6B;AAuBnC,OAAO,MAAMC;IAOX,YAAY,AAAiBC,OAAwC,CAAE;aAA1CA,UAAAA;QAC3B,IAAI,CAACC,QAAQ,GAAG,IAAIC,IAAIF,QAAQC,QAAQ,IAAIJ;QAC5C,IAAI,CAACM,aAAa,GAAGH,QAAQG,aAAa,IAAIL;QAC9C,IAAI,CAACM,YAAY,GAAGJ,QAAQI,YAAY,IAAIC;IAC9C;IAEAC,UAAU;QACR,OAAOX;IACT;IAEAY,mBAAmB;QACjB,OAAOX;IACT;IAEA,MAAMY,YACJC,KAA4F,EACjD;QAC3C,MAAMC,cAAc,MAAM,IAAI,CAACV,OAAO,CAACW,UAAU,CAACC,cAAc,CAAC;YAC/DC,cAAcJ,MAAMK,UAAU,CAACC,EAAE;QACnC;QACA,MAAMC,SAAS,MAAM,IAAI,CAACZ,YAAY,CAAC;YAACH,UAAU,IAAI,CAACA,QAAQ;YAAES;QAAW;QAE5E,OAAO;YACLO,MAAM,CAACA,OAASD,OAAOE,QAAQ,CAACD,MAAM,IAAI,CAACd,aAAa;YACxDgB,OAAO,IAAMH,OAAOG,KAAK;QAC3B;IACF;AACF;AAEA,eAAed,yBACbe,MAAmC;IAEnC,MAAMJ,SAAS,IAAIxB,OAAO;QAAC6B,MAAM;QAAwBC,SAAS;IAAO;IACzE,MAAMC,YAAY,IAAI9B,8BAA8B2B,OAAOnB,QAAQ,EAAE;QACnEuB,aAAa;YACXC,SAAS;gBAACC,eAAe,CAAC,OAAO,EAAEN,OAAOV,WAAW,EAAE;YAAA;QACzD;IACF;IAEA,MAAMM,OAAOW,OAAO,CAACJ;IAErB,OAAO;QACLL,UAAU,OAAOT,OAAOmB;YACtB,MAAMC,SAAS,MAAMb,OAAOE,QAAQ,CAClC;gBAACG,MAAMZ,MAAMqB,MAAM;gBAAEC,WAAWtB,MAAMsB,SAAS;YAAA,GAC/CrC,sBACA;gBACEsC,SAASJ;YACX;YAEF,OAAOC;QACT;QACAV,OAAO;YACL,MAAMH,OAAOG,KAAK;QACpB;IACF;AACF"}
@@ -1,4 +1,4 @@
1
- import type { AgentToolCatalogEntry, AgentToolSelectionCatalog } from '@shipfox/api-integration-core-dto';
1
+ import type { AgentToolCatalogEntry, AgentToolSelectionCatalog } from '@shipfox/api-integration-spi';
2
2
  export type LinearAgentToolRequiredScope = 'read' | 'write';
3
3
  export type LinearAgentToolCategory = 'issues' | 'comments' | 'projects' | 'documents' | 'workspace' | 'cycles' | 'releases' | 'release_notes' | 'agents' | 'diffs' | 'attachments' | 'documentation';
4
4
  export interface LinearAgentToolCatalogEntry extends AgentToolCatalogEntry<LinearAgentToolRequiredScope> {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tools.d.ts","sourceRoot":"","sources":["../../src/core/agent-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EAErB,yBAAyB,EAE1B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,MAAM,4BAA4B,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,uBAAuB,GAC/B,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,GACV,eAAe,GACf,QAAQ,GACR,OAAO,GACP,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,WAAW,2BACf,SAAQ,qBAAqB,CAAC,4BAA4B,CAAC;IAC3D,QAAQ,EAAE,uBAAuB,CAAC;CACnC;AA8BD,eAAO,MAAM,sBAAsB,81CA+xBwB,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAE9E,eAAO,MAAM,+BAA+B,2BACkB,CAAC"}
1
+ {"version":3,"file":"agent-tools.d.ts","sourceRoot":"","sources":["../../src/core/agent-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EAErB,yBAAyB,EAE1B,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,4BAA4B,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,uBAAuB,GAC/B,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,GACV,eAAe,GACf,QAAQ,GACR,OAAO,GACP,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,WAAW,2BACf,SAAQ,qBAAqB,CAAC,4BAA4B,CAAC;IAC3D,QAAQ,EAAE,uBAAuB,CAAC;CACnC;AA8BD,eAAO,MAAM,sBAAsB,81CA+xBwB,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAE9E,eAAO,MAAM,+BAA+B,2BACkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCatalogEntry,\n AgentToolJsonSchema,\n AgentToolSelectionCatalog,\n AgentToolSelector,\n} from '@shipfox/api-integration-core-dto';\n\nexport type LinearAgentToolRequiredScope = 'read' | 'write';\n\nexport type LinearAgentToolCategory =\n | 'issues'\n | 'comments'\n | 'projects'\n | 'documents'\n | 'workspace'\n | 'cycles'\n | 'releases'\n | 'release_notes'\n | 'agents'\n | 'diffs'\n | 'attachments'\n | 'documentation';\n\nexport interface LinearAgentToolCatalogEntry\n extends AgentToolCatalogEntry<LinearAgentToolRequiredScope> {\n category: LinearAgentToolCategory;\n}\n\ninterface LinearAgentToolCatalogInput {\n id: string;\n category: LinearAgentToolCategory;\n description: string;\n sensitivity: 'read' | 'write';\n sensitive: boolean;\n requiredScope: LinearAgentToolRequiredScope;\n inputSchema: AgentToolJsonSchema;\n}\n\nconst orderBySchema = enumSchema(['createdAt', 'updatedAt'], 'Sort order');\nconst cursorSchema = stringSchema('Next page cursor');\nconst limitSchema = numberSchema('Maximum number of results to return');\nconst dateFilterSchema = stringSchema('ISO-8601 date or duration filter');\nconst prioritySchema = numberSchema('0=None, 1=Urgent, 2=High, 3=Medium, 4=Low');\nconst nullableStringSchema = nullableSchema(stringSchema());\n\nconst pageProperties = {\n cursor: cursorSchema,\n limit: limitSchema,\n orderBy: orderBySchema,\n};\n\nconst timelineFilterProperties = {\n createdAt: dateFilterSchema,\n updatedAt: dateFilterSchema,\n};\n\nexport const linearAgentToolCatalog = [\n tool({\n id: 'get_attachment',\n category: 'attachments',\n description: 'Retrieve a Linear attachment by ID.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Attachment ID')}, ['id']),\n }),\n tool({\n id: 'get_agent_skill',\n category: 'agents',\n description: 'Retrieve a Linear Agent skill by ID, including its full markdown instructions.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Agent skill ID')}, ['id']),\n }),\n tool({\n id: 'get_diff',\n category: 'diffs',\n description: 'Look up a Linear diff by review URL, GitHub PR URL, identifier, UUID, or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n urlOrId: stringSchema(\n 'Linear review URL, diff slug, pull request ID, Linear identifier, or GitHub PR URL',\n ),\n },\n ['urlOrId'],\n ),\n }),\n tool({\n id: 'get_diff_threads',\n category: 'diffs',\n description:\n 'Look up Linear diff threads by review URL, GitHub PR URL, identifier, UUID, or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n orderBy: orderBySchema,\n resolved: booleanSchema('Filter returned threads by resolved state'),\n threadId: stringSchema('Top-level thread or comment ID to return'),\n urlOrId: stringSchema(\n 'Linear review URL, diff slug, pull request ID, Linear identifier, or GitHub PR URL',\n ),\n },\n ['urlOrId'],\n ),\n }),\n tool({\n id: 'get_document',\n category: 'documents',\n description: 'Retrieve a Linear document by ID or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Document ID or slug')}, ['id']),\n }),\n tool({\n id: 'get_issue',\n category: 'issues',\n description: 'Retrieve detailed information about a Linear issue.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Issue ID or identifier'),\n includeCustomerNeeds: booleanSchema('Include associated customer needs'),\n includeRelations: booleanSchema('Include blocking, related, and duplicate relations'),\n includeReleases: booleanSchema('Include associated releases'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'list_issues',\n category: 'issues',\n description: 'List Linear issues visible to the authenticated connection.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n assignee: nullableStringSchema,\n cycle: stringSchema('Cycle name, number, or ID'),\n delegate: stringSchema('Agent name or ID'),\n includeArchived: booleanSchema('Include archived issues'),\n label: stringSchema('Label name or ID'),\n parentId: stringSchema('Parent issue ID or identifier'),\n priority: prioritySchema,\n project: stringSchema('Project name, ID, or slug'),\n query: stringSchema('Search issue title or description'),\n release: stringSchema('Release ID or slug'),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_comments',\n category: 'comments',\n description: 'List comments on a Linear issue, project, initiative, document, or milestone.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n documentId: stringSchema('Document ID or slug'),\n initiativeId: stringSchema('Initiative name or ID'),\n issueId: stringSchema('Issue ID or identifier'),\n milestoneId: stringSchema('Milestone UUID'),\n projectId: stringSchema('Project name, ID, or slug'),\n }),\n }),\n tool({\n id: 'list_issue_labels',\n category: 'issues',\n description: 'List issue labels in a Linear workspace or team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n name: stringSchema('Filter by label name'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_issue_statuses',\n category: 'issues',\n description: 'List available issue statuses in a Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({team: stringSchema('Team name or ID')}, ['team']),\n }),\n tool({\n id: 'get_issue_status',\n category: 'issues',\n description: 'Retrieve detailed information about an issue status by name or ID.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Status ID'),\n name: stringSchema('Status name'),\n team: stringSchema('Team name or ID'),\n },\n ['id', 'name', 'team'],\n ),\n }),\n tool({\n id: 'list_teams',\n category: 'workspace',\n description: 'List teams in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived teams'),\n query: stringSchema('Search query'),\n }),\n }),\n tool({\n id: 'get_team',\n category: 'workspace',\n description: 'Retrieve detailed information about a Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({query: stringSchema('Team UUID, key, or name')}, ['query']),\n }),\n tool({\n id: 'list_users',\n category: 'workspace',\n description: 'Retrieve users in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n query: stringSchema('Filter by name or email'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_projects',\n category: 'projects',\n description: 'List projects in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived projects'),\n includeMembers: booleanSchema('Include project members'),\n includeMilestones: booleanSchema('Include milestones'),\n initiative: stringSchema('Initiative name or ID'),\n label: stringSchema('Label name or ID'),\n member: stringSchema('User ID, name, email, or \"me\"'),\n query: stringSchema('Search project name'),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'get_project',\n category: 'projects',\n description: 'Retrieve details of a specific Linear project.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n includeMembers: booleanSchema('Include project members'),\n includeMilestones: booleanSchema('Include milestones'),\n includeResources: booleanSchema('Include documents, links, and attachments'),\n query: stringSchema('Project name, ID, or slug'),\n },\n ['query'],\n ),\n }),\n tool({\n id: 'list_project_labels',\n category: 'projects',\n description: 'List project labels in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n name: stringSchema('Filter by label name'),\n }),\n }),\n tool({\n id: 'list_milestones',\n category: 'projects',\n description: 'List milestones in a Linear project.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({project: stringSchema('Project name, ID, or slug')}, ['project']),\n }),\n tool({\n id: 'get_milestone',\n category: 'projects',\n description: 'Retrieve details of a Linear milestone by ID or name.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n project: stringSchema('Project name, ID, or slug'),\n query: stringSchema('Milestone name or ID'),\n },\n ['project', 'query'],\n ),\n }),\n tool({\n id: 'get_release',\n category: 'releases',\n description: 'Retrieve details of a Linear release by ID or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Release ID or slug'),\n includeReleaseNotes: booleanSchema('Include associated release notes'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'get_release_note',\n category: 'release_notes',\n description: 'Retrieve Linear release notes by ID or slug, including markdown content.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Release notes ID or slug'),\n includeReleases: booleanSchema('Include associated releases'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'list_cycles',\n category: 'cycles',\n description: 'Retrieve cycles for a specific Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n teamId: stringSchema('Team ID'),\n type: enumSchema(['current', 'previous', 'next'], 'Cycle filter'),\n },\n ['teamId'],\n ),\n }),\n tool({\n id: 'list_documents',\n category: 'documents',\n description: 'List documents in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n creatorId: stringSchema('Creator ID'),\n includeArchived: booleanSchema('Include archived documents'),\n initiativeId: stringSchema('Initiative ID'),\n projectId: stringSchema('Project ID'),\n query: stringSchema('Search query'),\n teamId: stringSchema('Team ID'),\n }),\n }),\n tool({\n id: 'get_status_updates',\n category: 'projects',\n description: 'List or retrieve project or initiative status updates.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n ...pageProperties,\n ...timelineFilterProperties,\n id: stringSchema('Status update ID'),\n includeArchived: booleanSchema('Include archived updates'),\n initiative: stringSchema('Initiative name or ID'),\n project: stringSchema('Project name, ID, or slug'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n user: stringSchema('User ID, name, email, or \"me\"'),\n },\n ['type'],\n ),\n }),\n tool({\n id: 'list_release_notes',\n category: 'release_notes',\n description: 'List release notes in the workspace, optionally filtered by pipeline or release.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived release notes'),\n includeContent: booleanSchema('Include markdown release notes content'),\n includeReleases: booleanSchema('Include associated releases'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n query: stringSchema('Search release notes title'),\n release: stringSchema('Release ID or slug'),\n }),\n }),\n tool({\n id: 'list_release_pipelines',\n category: 'releases',\n description: 'List release pipelines in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived release pipelines'),\n includeStages: booleanSchema('Include each pipeline stages'),\n includeTeams: booleanSchema('Include each pipeline teams'),\n isProduction: booleanSchema('Filter by production pipeline flag'),\n query: stringSchema('Search pipeline name'),\n team: stringSchema('Team name or ID'),\n type: enumSchema(['continuous', 'scheduled'], 'Pipeline type'),\n }),\n }),\n tool({\n id: 'list_releases',\n category: 'releases',\n description:\n 'List releases in the workspace, with optional filtering by pipeline, stage, version, and text.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n hasReleaseNotes: booleanSchema('Filter to releases that do or do not have release notes'),\n includeArchived: booleanSchema('Include archived releases'),\n includeReleaseNotes: booleanSchema('Include associated release notes'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n query: stringSchema('Search release name or version'),\n stage: stringSchema('Release stage ID or exact name'),\n stageType: enumSchema(\n ['planned', 'started', 'completed', 'canceled'],\n 'Stage lifecycle type',\n ),\n version: stringSchema('Exact version match'),\n }),\n }),\n tool({\n id: 'list_agent_skills',\n category: 'agents',\n description: 'List Linear Agent skills available to the authenticated user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(pageProperties),\n }),\n tool({\n id: 'get_user',\n category: 'workspace',\n description: 'Retrieve details of a specific Linear user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({query: stringSchema('User ID, name, email, or \"me\"')}, ['query']),\n }),\n tool({\n id: 'list_diffs',\n category: 'diffs',\n description: 'List Linear diff pull requests visible to the authenticated user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n owner: stringSchema('Repository owner'),\n query: stringSchema('Search by title, branch, PR number, or bare slug'),\n repo: stringSchema('Repository name'),\n status: stringSchema('Pull request status'),\n }),\n }),\n tool({\n id: 'extract_images',\n category: 'attachments',\n description: 'Extract and fetch images from markdown content.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {markdown: stringSchema('Markdown content containing image references')},\n ['markdown'],\n ),\n }),\n tool({\n id: 'search_documentation',\n category: 'documentation',\n description: \"Search Linear's documentation to learn about features and usage.\",\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n page: numberSchema('Page number'),\n query: stringSchema('Search query'),\n },\n ['query'],\n ),\n }),\n tool({\n id: 'create_attachment',\n category: 'attachments',\n description: 'Upload a tiny file through the MCP worker and attach it to a Linear issue.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n base64Content: stringSchema('Deprecated base64-encoded file content to upload'),\n contentType: stringSchema('MIME type for the upload'),\n filename: stringSchema('Filename for the upload'),\n issue: stringSchema('Issue ID or identifier'),\n sha256: stringSchema('Expected SHA-256 hex digest of the decoded file bytes'),\n size: numberSchema('Expected decoded file size in bytes'),\n subtitle: stringSchema('Attachment subtitle'),\n title: stringSchema('Attachment title'),\n },\n ['base64Content', 'contentType', 'filename', 'issue', 'sha256'],\n ),\n }),\n tool({\n id: 'create_attachment_from_upload',\n category: 'attachments',\n description: 'Link an already-uploaded Linear asset URL to an existing issue as an attachment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n assetUrl: stringSchema('Linear upload asset URL returned by prepare_attachment_upload'),\n issue: stringSchema('Issue ID or identifier'),\n subtitle: stringSchema('Attachment subtitle'),\n title: stringSchema('Attachment title'),\n },\n ['assetUrl', 'issue'],\n ),\n }),\n tool({\n id: 'prepare_attachment_upload',\n category: 'attachments',\n description: 'Prepare a direct Linear file upload for an existing issue.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n contentType: stringSchema('MIME type for the upload'),\n filename: stringSchema('Filename for the upload'),\n issue: stringSchema('Issue ID or identifier'),\n size: numberSchema('Exact file size in bytes'),\n subtitle: stringSchema('Suggested attachment subtitle for the finalize step'),\n title: stringSchema('Suggested attachment title for the finalize step'),\n },\n ['contentType', 'filename', 'issue', 'size'],\n ),\n }),\n tool({\n id: 'save_issue',\n category: 'issues',\n description: 'Create or update a Linear issue.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n addReleases: arraySchema(stringSchema('Release ID or slug')),\n assignee: nullableStringSchema,\n blockedBy: arraySchema(stringSchema('Blocking issue ID or identifier')),\n blocks: arraySchema(stringSchema('Blocked issue ID or identifier')),\n cycle: nullableStringSchema,\n delegate: nullableStringSchema,\n description: stringSchema('Issue description as Markdown'),\n dueDate: stringSchema('Due date in ISO format'),\n duplicateOf: nullableStringSchema,\n estimate: nullableSchema(numberSchema('Issue estimate value')),\n id: stringSchema('Issue ID or identifier'),\n labels: arraySchema(stringSchema('Label name or ID')),\n links: arraySchema(\n objectSchema(\n {\n title: stringSchema('Attachment title'),\n url: stringSchema('Attachment URL'),\n },\n ['title', 'url'],\n ),\n ),\n milestone: stringSchema('Milestone name or ID'),\n parentId: nullableStringSchema,\n priority: prioritySchema,\n project: nullableStringSchema,\n relatedTo: arraySchema(stringSchema('Related issue ID or identifier')),\n removeBlockedBy: arraySchema(stringSchema('Blocking issue ID or identifier to remove')),\n removeBlocks: arraySchema(stringSchema('Blocked issue ID or identifier to remove')),\n removeRelatedTo: arraySchema(stringSchema('Related issue ID or identifier to remove')),\n removeReleases: arraySchema(stringSchema('Release ID or slug to remove')),\n setReleases: arraySchema(stringSchema('Release ID or slug')),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n title: stringSchema('Issue title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_comment',\n category: 'comments',\n description:\n 'Create or update a comment on a Linear issue, project, initiative, document, or milestone.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n body: stringSchema('Comment body as Markdown'),\n documentId: stringSchema('Document ID or slug'),\n id: stringSchema('Comment ID'),\n initiativeId: stringSchema('Initiative name or ID'),\n issueId: stringSchema('Issue ID or identifier'),\n milestoneId: stringSchema('Milestone UUID'),\n parentId: stringSchema('Parent comment ID'),\n projectId: stringSchema('Project name, ID, or slug'),\n },\n ['body'],\n ),\n }),\n tool({\n id: 'save_project',\n category: 'projects',\n description: 'Create or update a Linear project.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n addInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n addTeams: arraySchema(stringSchema('Team name or ID')),\n color: stringSchema('Hex color'),\n description: stringSchema('Project description as Markdown'),\n icon: stringSchema('Icon name or emoji code'),\n id: stringSchema('Project ID'),\n labels: arraySchema(stringSchema('Label name or ID')),\n lead: nullableStringSchema,\n name: stringSchema('Project name'),\n priority: prioritySchema,\n removeInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n removeTeams: arraySchema(stringSchema('Team name or ID')),\n setInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n setTeams: arraySchema(stringSchema('Team name or ID')),\n startDate: stringSchema('Start date in ISO format'),\n startDateResolution: enumSchema(\n ['halfYear', 'month', 'quarter', 'year'],\n 'Start date resolution',\n ),\n state: stringSchema('Project state'),\n summary: stringSchema('Short summary'),\n targetDate: stringSchema('Target date in ISO format'),\n targetDateResolution: enumSchema(\n ['halfYear', 'month', 'quarter', 'year'],\n 'Target date resolution',\n ),\n },\n [],\n ),\n }),\n tool({\n id: 'save_document',\n category: 'documents',\n description: 'Create or update a Linear document.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n color: stringSchema('Hex color'),\n content: stringSchema('Document content as Markdown'),\n cycle: stringSchema('Cycle name, number, or ID'),\n icon: stringSchema('Icon name or emoji code'),\n id: stringSchema('Document ID or slug'),\n initiative: stringSchema('Initiative name or ID'),\n issue: stringSchema('Issue ID or identifier'),\n project: stringSchema('Project name, ID, or slug'),\n team: stringSchema('Team name or ID'),\n title: stringSchema('Document title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_milestone',\n category: 'projects',\n description: 'Create or update a Linear milestone in a project.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n description: stringSchema('Milestone description'),\n id: stringSchema('Milestone name or ID'),\n name: stringSchema('Milestone name'),\n project: stringSchema('Project name, ID, or slug'),\n targetDate: nullableStringSchema,\n },\n ['project'],\n ),\n }),\n tool({\n id: 'save_release',\n category: 'releases',\n description: 'Create or update a Linear release.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n commitSha: stringSchema('Commit SHA associated with the release'),\n completedAt: nullableSchema(stringSchema('Completed timestamp in ISO DateTime format')),\n createdAt: stringSchema('Import or create timestamp in ISO DateTime format'),\n description: stringSchema('Release description'),\n id: stringSchema('Release ID or slug to update'),\n name: stringSchema('Release name'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n stage: stringSchema('Release stage ID, exact name, or lifecycle type within the pipeline'),\n startDate: nullableSchema(stringSchema('Estimated start date in ISO YYYY-MM-DD format')),\n startedAt: nullableSchema(stringSchema('Started timestamp in ISO DateTime format')),\n targetDate: nullableSchema(\n stringSchema('Estimated completion date in ISO YYYY-MM-DD format'),\n ),\n version: stringSchema('Version identifier'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_release_note',\n category: 'release_notes',\n description: 'Create or update Linear release notes.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n content: stringSchema('Release notes content as Markdown'),\n id: stringSchema('Release notes ID or slug to update'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n rangeFromRelease: stringSchema('Oldest release ID or slug in the note range'),\n rangeToRelease: stringSchema('Newest release ID or slug in the note range'),\n releases: arraySchema(stringSchema('Release ID or slug')),\n title: stringSchema('Release notes title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_status_update',\n category: 'projects',\n description: 'Create or update a project or initiative status update.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n body: stringSchema('Status update body as Markdown'),\n health: enumSchema(['onTrack', 'atRisk', 'offTrack'], 'Status update health'),\n id: stringSchema('Status update ID'),\n initiative: stringSchema('Initiative name or ID'),\n isDiffHidden: booleanSchema('Hide diff with previous update'),\n project: stringSchema('Project name, ID, or slug'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n },\n ['type'],\n ),\n }),\n tool({\n id: 'create_issue_label',\n category: 'issues',\n description: 'Create a new Linear issue label.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n color: stringSchema('Hex color code'),\n description: stringSchema('Label description'),\n isGroup: booleanSchema('Is label group'),\n name: stringSchema('Label name'),\n parent: stringSchema('Parent label group name'),\n teamId: stringSchema('Team UUID'),\n },\n ['name'],\n ),\n }),\n tool({\n id: 'delete_comment',\n category: 'comments',\n description: 'Delete a Linear comment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema({id: stringSchema('Comment ID')}, ['id']),\n }),\n tool({\n id: 'delete_status_update',\n category: 'projects',\n description: 'Delete or archive a Linear project or initiative status update.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n id: stringSchema('Status update ID'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n },\n ['id', 'type'],\n ),\n }),\n tool({\n id: 'delete_attachment',\n category: 'attachments',\n description: 'Delete a Linear attachment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema({id: stringSchema('Attachment ID')}, ['id']),\n }),\n] as const satisfies readonly LinearAgentToolCatalogEntry[];\n\nexport type LinearAgentToolId = (typeof linearAgentToolCatalog)[number]['id'];\n\nexport const linearAgentToolSelectionCatalog =\n buildLinearAgentToolSelectionCatalog(linearAgentToolCatalog);\n\nfunction buildLinearAgentToolSelectionCatalog(\n catalog: readonly LinearAgentToolCatalogEntry[],\n): AgentToolSelectionCatalog {\n return {\n selectors: catalog.map(\n (entry): AgentToolSelector => ({\n token: entry.id,\n kind: 'standalone',\n sensitivity: entry.sensitivity,\n sensitive: entry.sensitive,\n }),\n ),\n };\n}\n\nfunction tool(input: LinearAgentToolCatalogInput): LinearAgentToolCatalogEntry {\n return input;\n}\n\nfunction objectSchema(\n properties: Record<string, AgentToolJsonSchema>,\n required: string[] = [],\n extraSchema: Partial<AgentToolJsonSchema> = {},\n): AgentToolJsonSchema {\n return {\n type: 'object',\n additionalProperties: false,\n properties,\n ...(required.length > 0 ? {required} : {}),\n ...extraSchema,\n };\n}\n\nfunction stringSchema(description?: string): AgentToolJsonSchema {\n return {type: 'string', ...(description ? {description} : {})};\n}\n\nfunction numberSchema(description?: string): AgentToolJsonSchema {\n return {type: 'number', ...(description ? {description} : {})};\n}\n\nfunction booleanSchema(description: string): AgentToolJsonSchema {\n return {type: 'boolean', description};\n}\n\nfunction enumSchema(values: string[], description: string): AgentToolJsonSchema {\n return {type: 'string', description, enum: values};\n}\n\nfunction arraySchema(items: AgentToolJsonSchema): AgentToolJsonSchema {\n return {type: 'array', items};\n}\n\nfunction nullableSchema(schema: AgentToolJsonSchema): AgentToolJsonSchema {\n return {anyOf: [schema, {type: 'null'}]};\n}\n"],"names":["orderBySchema","enumSchema","cursorSchema","stringSchema","limitSchema","numberSchema","dateFilterSchema","prioritySchema","nullableStringSchema","nullableSchema","pageProperties","cursor","limit","orderBy","timelineFilterProperties","createdAt","updatedAt","linearAgentToolCatalog","tool","id","category","description","sensitivity","sensitive","requiredScope","inputSchema","objectSchema","urlOrId","resolved","booleanSchema","threadId","includeCustomerNeeds","includeRelations","includeReleases","assignee","cycle","delegate","includeArchived","label","parentId","priority","project","query","release","state","team","documentId","initiativeId","issueId","milestoneId","projectId","name","includeMembers","includeMilestones","initiative","member","includeResources","includeReleaseNotes","teamId","type","creatorId","user","includeContent","pipeline","includeStages","includeTeams","isProduction","hasReleaseNotes","stage","stageType","version","owner","repo","status","markdown","page","base64Content","contentType","filename","issue","sha256","size","subtitle","title","assetUrl","addReleases","arraySchema","blockedBy","blocks","dueDate","duplicateOf","estimate","labels","links","url","milestone","relatedTo","removeBlockedBy","removeBlocks","removeRelatedTo","removeReleases","setReleases","body","addInitiatives","addTeams","color","icon","lead","removeInitiatives","removeTeams","setInitiatives","setTeams","startDate","startDateResolution","summary","targetDate","targetDateResolution","content","commitSha","completedAt","startedAt","rangeFromRelease","rangeToRelease","releases","health","isDiffHidden","isGroup","parent","linearAgentToolSelectionCatalog","buildLinearAgentToolSelectionCatalog","catalog","selectors","map","entry","token","kind","input","properties","required","extraSchema","additionalProperties","length","values","enum","items","schema","anyOf"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCatalogEntry,\n AgentToolJsonSchema,\n AgentToolSelectionCatalog,\n AgentToolSelector,\n} from '@shipfox/api-integration-spi';\n\nexport type LinearAgentToolRequiredScope = 'read' | 'write';\n\nexport type LinearAgentToolCategory =\n | 'issues'\n | 'comments'\n | 'projects'\n | 'documents'\n | 'workspace'\n | 'cycles'\n | 'releases'\n | 'release_notes'\n | 'agents'\n | 'diffs'\n | 'attachments'\n | 'documentation';\n\nexport interface LinearAgentToolCatalogEntry\n extends AgentToolCatalogEntry<LinearAgentToolRequiredScope> {\n category: LinearAgentToolCategory;\n}\n\ninterface LinearAgentToolCatalogInput {\n id: string;\n category: LinearAgentToolCategory;\n description: string;\n sensitivity: 'read' | 'write';\n sensitive: boolean;\n requiredScope: LinearAgentToolRequiredScope;\n inputSchema: AgentToolJsonSchema;\n}\n\nconst orderBySchema = enumSchema(['createdAt', 'updatedAt'], 'Sort order');\nconst cursorSchema = stringSchema('Next page cursor');\nconst limitSchema = numberSchema('Maximum number of results to return');\nconst dateFilterSchema = stringSchema('ISO-8601 date or duration filter');\nconst prioritySchema = numberSchema('0=None, 1=Urgent, 2=High, 3=Medium, 4=Low');\nconst nullableStringSchema = nullableSchema(stringSchema());\n\nconst pageProperties = {\n cursor: cursorSchema,\n limit: limitSchema,\n orderBy: orderBySchema,\n};\n\nconst timelineFilterProperties = {\n createdAt: dateFilterSchema,\n updatedAt: dateFilterSchema,\n};\n\nexport const linearAgentToolCatalog = [\n tool({\n id: 'get_attachment',\n category: 'attachments',\n description: 'Retrieve a Linear attachment by ID.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Attachment ID')}, ['id']),\n }),\n tool({\n id: 'get_agent_skill',\n category: 'agents',\n description: 'Retrieve a Linear Agent skill by ID, including its full markdown instructions.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Agent skill ID')}, ['id']),\n }),\n tool({\n id: 'get_diff',\n category: 'diffs',\n description: 'Look up a Linear diff by review URL, GitHub PR URL, identifier, UUID, or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n urlOrId: stringSchema(\n 'Linear review URL, diff slug, pull request ID, Linear identifier, or GitHub PR URL',\n ),\n },\n ['urlOrId'],\n ),\n }),\n tool({\n id: 'get_diff_threads',\n category: 'diffs',\n description:\n 'Look up Linear diff threads by review URL, GitHub PR URL, identifier, UUID, or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n orderBy: orderBySchema,\n resolved: booleanSchema('Filter returned threads by resolved state'),\n threadId: stringSchema('Top-level thread or comment ID to return'),\n urlOrId: stringSchema(\n 'Linear review URL, diff slug, pull request ID, Linear identifier, or GitHub PR URL',\n ),\n },\n ['urlOrId'],\n ),\n }),\n tool({\n id: 'get_document',\n category: 'documents',\n description: 'Retrieve a Linear document by ID or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({id: stringSchema('Document ID or slug')}, ['id']),\n }),\n tool({\n id: 'get_issue',\n category: 'issues',\n description: 'Retrieve detailed information about a Linear issue.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Issue ID or identifier'),\n includeCustomerNeeds: booleanSchema('Include associated customer needs'),\n includeRelations: booleanSchema('Include blocking, related, and duplicate relations'),\n includeReleases: booleanSchema('Include associated releases'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'list_issues',\n category: 'issues',\n description: 'List Linear issues visible to the authenticated connection.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n assignee: nullableStringSchema,\n cycle: stringSchema('Cycle name, number, or ID'),\n delegate: stringSchema('Agent name or ID'),\n includeArchived: booleanSchema('Include archived issues'),\n label: stringSchema('Label name or ID'),\n parentId: stringSchema('Parent issue ID or identifier'),\n priority: prioritySchema,\n project: stringSchema('Project name, ID, or slug'),\n query: stringSchema('Search issue title or description'),\n release: stringSchema('Release ID or slug'),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_comments',\n category: 'comments',\n description: 'List comments on a Linear issue, project, initiative, document, or milestone.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n documentId: stringSchema('Document ID or slug'),\n initiativeId: stringSchema('Initiative name or ID'),\n issueId: stringSchema('Issue ID or identifier'),\n milestoneId: stringSchema('Milestone UUID'),\n projectId: stringSchema('Project name, ID, or slug'),\n }),\n }),\n tool({\n id: 'list_issue_labels',\n category: 'issues',\n description: 'List issue labels in a Linear workspace or team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n name: stringSchema('Filter by label name'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_issue_statuses',\n category: 'issues',\n description: 'List available issue statuses in a Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({team: stringSchema('Team name or ID')}, ['team']),\n }),\n tool({\n id: 'get_issue_status',\n category: 'issues',\n description: 'Retrieve detailed information about an issue status by name or ID.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Status ID'),\n name: stringSchema('Status name'),\n team: stringSchema('Team name or ID'),\n },\n ['id', 'name', 'team'],\n ),\n }),\n tool({\n id: 'list_teams',\n category: 'workspace',\n description: 'List teams in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived teams'),\n query: stringSchema('Search query'),\n }),\n }),\n tool({\n id: 'get_team',\n category: 'workspace',\n description: 'Retrieve detailed information about a Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({query: stringSchema('Team UUID, key, or name')}, ['query']),\n }),\n tool({\n id: 'list_users',\n category: 'workspace',\n description: 'Retrieve users in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n query: stringSchema('Filter by name or email'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'list_projects',\n category: 'projects',\n description: 'List projects in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived projects'),\n includeMembers: booleanSchema('Include project members'),\n includeMilestones: booleanSchema('Include milestones'),\n initiative: stringSchema('Initiative name or ID'),\n label: stringSchema('Label name or ID'),\n member: stringSchema('User ID, name, email, or \"me\"'),\n query: stringSchema('Search project name'),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n }),\n }),\n tool({\n id: 'get_project',\n category: 'projects',\n description: 'Retrieve details of a specific Linear project.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n includeMembers: booleanSchema('Include project members'),\n includeMilestones: booleanSchema('Include milestones'),\n includeResources: booleanSchema('Include documents, links, and attachments'),\n query: stringSchema('Project name, ID, or slug'),\n },\n ['query'],\n ),\n }),\n tool({\n id: 'list_project_labels',\n category: 'projects',\n description: 'List project labels in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n name: stringSchema('Filter by label name'),\n }),\n }),\n tool({\n id: 'list_milestones',\n category: 'projects',\n description: 'List milestones in a Linear project.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({project: stringSchema('Project name, ID, or slug')}, ['project']),\n }),\n tool({\n id: 'get_milestone',\n category: 'projects',\n description: 'Retrieve details of a Linear milestone by ID or name.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n project: stringSchema('Project name, ID, or slug'),\n query: stringSchema('Milestone name or ID'),\n },\n ['project', 'query'],\n ),\n }),\n tool({\n id: 'get_release',\n category: 'releases',\n description: 'Retrieve details of a Linear release by ID or slug.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Release ID or slug'),\n includeReleaseNotes: booleanSchema('Include associated release notes'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'get_release_note',\n category: 'release_notes',\n description: 'Retrieve Linear release notes by ID or slug, including markdown content.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n id: stringSchema('Release notes ID or slug'),\n includeReleases: booleanSchema('Include associated releases'),\n },\n ['id'],\n ),\n }),\n tool({\n id: 'list_cycles',\n category: 'cycles',\n description: 'Retrieve cycles for a specific Linear team.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n teamId: stringSchema('Team ID'),\n type: enumSchema(['current', 'previous', 'next'], 'Cycle filter'),\n },\n ['teamId'],\n ),\n }),\n tool({\n id: 'list_documents',\n category: 'documents',\n description: 'List documents in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n creatorId: stringSchema('Creator ID'),\n includeArchived: booleanSchema('Include archived documents'),\n initiativeId: stringSchema('Initiative ID'),\n projectId: stringSchema('Project ID'),\n query: stringSchema('Search query'),\n teamId: stringSchema('Team ID'),\n }),\n }),\n tool({\n id: 'get_status_updates',\n category: 'projects',\n description: 'List or retrieve project or initiative status updates.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n ...pageProperties,\n ...timelineFilterProperties,\n id: stringSchema('Status update ID'),\n includeArchived: booleanSchema('Include archived updates'),\n initiative: stringSchema('Initiative name or ID'),\n project: stringSchema('Project name, ID, or slug'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n user: stringSchema('User ID, name, email, or \"me\"'),\n },\n ['type'],\n ),\n }),\n tool({\n id: 'list_release_notes',\n category: 'release_notes',\n description: 'List release notes in the workspace, optionally filtered by pipeline or release.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived release notes'),\n includeContent: booleanSchema('Include markdown release notes content'),\n includeReleases: booleanSchema('Include associated releases'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n query: stringSchema('Search release notes title'),\n release: stringSchema('Release ID or slug'),\n }),\n }),\n tool({\n id: 'list_release_pipelines',\n category: 'releases',\n description: 'List release pipelines in the Linear workspace.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n includeArchived: booleanSchema('Include archived release pipelines'),\n includeStages: booleanSchema('Include each pipeline stages'),\n includeTeams: booleanSchema('Include each pipeline teams'),\n isProduction: booleanSchema('Filter by production pipeline flag'),\n query: stringSchema('Search pipeline name'),\n team: stringSchema('Team name or ID'),\n type: enumSchema(['continuous', 'scheduled'], 'Pipeline type'),\n }),\n }),\n tool({\n id: 'list_releases',\n category: 'releases',\n description:\n 'List releases in the workspace, with optional filtering by pipeline, stage, version, and text.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n ...timelineFilterProperties,\n hasReleaseNotes: booleanSchema('Filter to releases that do or do not have release notes'),\n includeArchived: booleanSchema('Include archived releases'),\n includeReleaseNotes: booleanSchema('Include associated release notes'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n query: stringSchema('Search release name or version'),\n stage: stringSchema('Release stage ID or exact name'),\n stageType: enumSchema(\n ['planned', 'started', 'completed', 'canceled'],\n 'Stage lifecycle type',\n ),\n version: stringSchema('Exact version match'),\n }),\n }),\n tool({\n id: 'list_agent_skills',\n category: 'agents',\n description: 'List Linear Agent skills available to the authenticated user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(pageProperties),\n }),\n tool({\n id: 'get_user',\n category: 'workspace',\n description: 'Retrieve details of a specific Linear user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({query: stringSchema('User ID, name, email, or \"me\"')}, ['query']),\n }),\n tool({\n id: 'list_diffs',\n category: 'diffs',\n description: 'List Linear diff pull requests visible to the authenticated user.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n ...pageProperties,\n owner: stringSchema('Repository owner'),\n query: stringSchema('Search by title, branch, PR number, or bare slug'),\n repo: stringSchema('Repository name'),\n status: stringSchema('Pull request status'),\n }),\n }),\n tool({\n id: 'extract_images',\n category: 'attachments',\n description: 'Extract and fetch images from markdown content.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {markdown: stringSchema('Markdown content containing image references')},\n ['markdown'],\n ),\n }),\n tool({\n id: 'search_documentation',\n category: 'documentation',\n description: \"Search Linear's documentation to learn about features and usage.\",\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n page: numberSchema('Page number'),\n query: stringSchema('Search query'),\n },\n ['query'],\n ),\n }),\n tool({\n id: 'create_attachment',\n category: 'attachments',\n description: 'Upload a tiny file through the MCP worker and attach it to a Linear issue.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n base64Content: stringSchema('Deprecated base64-encoded file content to upload'),\n contentType: stringSchema('MIME type for the upload'),\n filename: stringSchema('Filename for the upload'),\n issue: stringSchema('Issue ID or identifier'),\n sha256: stringSchema('Expected SHA-256 hex digest of the decoded file bytes'),\n size: numberSchema('Expected decoded file size in bytes'),\n subtitle: stringSchema('Attachment subtitle'),\n title: stringSchema('Attachment title'),\n },\n ['base64Content', 'contentType', 'filename', 'issue', 'sha256'],\n ),\n }),\n tool({\n id: 'create_attachment_from_upload',\n category: 'attachments',\n description: 'Link an already-uploaded Linear asset URL to an existing issue as an attachment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n assetUrl: stringSchema('Linear upload asset URL returned by prepare_attachment_upload'),\n issue: stringSchema('Issue ID or identifier'),\n subtitle: stringSchema('Attachment subtitle'),\n title: stringSchema('Attachment title'),\n },\n ['assetUrl', 'issue'],\n ),\n }),\n tool({\n id: 'prepare_attachment_upload',\n category: 'attachments',\n description: 'Prepare a direct Linear file upload for an existing issue.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n contentType: stringSchema('MIME type for the upload'),\n filename: stringSchema('Filename for the upload'),\n issue: stringSchema('Issue ID or identifier'),\n size: numberSchema('Exact file size in bytes'),\n subtitle: stringSchema('Suggested attachment subtitle for the finalize step'),\n title: stringSchema('Suggested attachment title for the finalize step'),\n },\n ['contentType', 'filename', 'issue', 'size'],\n ),\n }),\n tool({\n id: 'save_issue',\n category: 'issues',\n description: 'Create or update a Linear issue.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n addReleases: arraySchema(stringSchema('Release ID or slug')),\n assignee: nullableStringSchema,\n blockedBy: arraySchema(stringSchema('Blocking issue ID or identifier')),\n blocks: arraySchema(stringSchema('Blocked issue ID or identifier')),\n cycle: nullableStringSchema,\n delegate: nullableStringSchema,\n description: stringSchema('Issue description as Markdown'),\n dueDate: stringSchema('Due date in ISO format'),\n duplicateOf: nullableStringSchema,\n estimate: nullableSchema(numberSchema('Issue estimate value')),\n id: stringSchema('Issue ID or identifier'),\n labels: arraySchema(stringSchema('Label name or ID')),\n links: arraySchema(\n objectSchema(\n {\n title: stringSchema('Attachment title'),\n url: stringSchema('Attachment URL'),\n },\n ['title', 'url'],\n ),\n ),\n milestone: stringSchema('Milestone name or ID'),\n parentId: nullableStringSchema,\n priority: prioritySchema,\n project: nullableStringSchema,\n relatedTo: arraySchema(stringSchema('Related issue ID or identifier')),\n removeBlockedBy: arraySchema(stringSchema('Blocking issue ID or identifier to remove')),\n removeBlocks: arraySchema(stringSchema('Blocked issue ID or identifier to remove')),\n removeRelatedTo: arraySchema(stringSchema('Related issue ID or identifier to remove')),\n removeReleases: arraySchema(stringSchema('Release ID or slug to remove')),\n setReleases: arraySchema(stringSchema('Release ID or slug')),\n state: stringSchema('State type, name, or ID'),\n team: stringSchema('Team name or ID'),\n title: stringSchema('Issue title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_comment',\n category: 'comments',\n description:\n 'Create or update a comment on a Linear issue, project, initiative, document, or milestone.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n body: stringSchema('Comment body as Markdown'),\n documentId: stringSchema('Document ID or slug'),\n id: stringSchema('Comment ID'),\n initiativeId: stringSchema('Initiative name or ID'),\n issueId: stringSchema('Issue ID or identifier'),\n milestoneId: stringSchema('Milestone UUID'),\n parentId: stringSchema('Parent comment ID'),\n projectId: stringSchema('Project name, ID, or slug'),\n },\n ['body'],\n ),\n }),\n tool({\n id: 'save_project',\n category: 'projects',\n description: 'Create or update a Linear project.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n addInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n addTeams: arraySchema(stringSchema('Team name or ID')),\n color: stringSchema('Hex color'),\n description: stringSchema('Project description as Markdown'),\n icon: stringSchema('Icon name or emoji code'),\n id: stringSchema('Project ID'),\n labels: arraySchema(stringSchema('Label name or ID')),\n lead: nullableStringSchema,\n name: stringSchema('Project name'),\n priority: prioritySchema,\n removeInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n removeTeams: arraySchema(stringSchema('Team name or ID')),\n setInitiatives: arraySchema(stringSchema('Initiative name or ID')),\n setTeams: arraySchema(stringSchema('Team name or ID')),\n startDate: stringSchema('Start date in ISO format'),\n startDateResolution: enumSchema(\n ['halfYear', 'month', 'quarter', 'year'],\n 'Start date resolution',\n ),\n state: stringSchema('Project state'),\n summary: stringSchema('Short summary'),\n targetDate: stringSchema('Target date in ISO format'),\n targetDateResolution: enumSchema(\n ['halfYear', 'month', 'quarter', 'year'],\n 'Target date resolution',\n ),\n },\n [],\n ),\n }),\n tool({\n id: 'save_document',\n category: 'documents',\n description: 'Create or update a Linear document.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n color: stringSchema('Hex color'),\n content: stringSchema('Document content as Markdown'),\n cycle: stringSchema('Cycle name, number, or ID'),\n icon: stringSchema('Icon name or emoji code'),\n id: stringSchema('Document ID or slug'),\n initiative: stringSchema('Initiative name or ID'),\n issue: stringSchema('Issue ID or identifier'),\n project: stringSchema('Project name, ID, or slug'),\n team: stringSchema('Team name or ID'),\n title: stringSchema('Document title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_milestone',\n category: 'projects',\n description: 'Create or update a Linear milestone in a project.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n description: stringSchema('Milestone description'),\n id: stringSchema('Milestone name or ID'),\n name: stringSchema('Milestone name'),\n project: stringSchema('Project name, ID, or slug'),\n targetDate: nullableStringSchema,\n },\n ['project'],\n ),\n }),\n tool({\n id: 'save_release',\n category: 'releases',\n description: 'Create or update a Linear release.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n commitSha: stringSchema('Commit SHA associated with the release'),\n completedAt: nullableSchema(stringSchema('Completed timestamp in ISO DateTime format')),\n createdAt: stringSchema('Import or create timestamp in ISO DateTime format'),\n description: stringSchema('Release description'),\n id: stringSchema('Release ID or slug to update'),\n name: stringSchema('Release name'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n stage: stringSchema('Release stage ID, exact name, or lifecycle type within the pipeline'),\n startDate: nullableSchema(stringSchema('Estimated start date in ISO YYYY-MM-DD format')),\n startedAt: nullableSchema(stringSchema('Started timestamp in ISO DateTime format')),\n targetDate: nullableSchema(\n stringSchema('Estimated completion date in ISO YYYY-MM-DD format'),\n ),\n version: stringSchema('Version identifier'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_release_note',\n category: 'release_notes',\n description: 'Create or update Linear release notes.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n content: stringSchema('Release notes content as Markdown'),\n id: stringSchema('Release notes ID or slug to update'),\n pipeline: stringSchema('Release pipeline ID, slug, or exact name'),\n rangeFromRelease: stringSchema('Oldest release ID or slug in the note range'),\n rangeToRelease: stringSchema('Newest release ID or slug in the note range'),\n releases: arraySchema(stringSchema('Release ID or slug')),\n title: stringSchema('Release notes title'),\n },\n [],\n ),\n }),\n tool({\n id: 'save_status_update',\n category: 'projects',\n description: 'Create or update a project or initiative status update.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n body: stringSchema('Status update body as Markdown'),\n health: enumSchema(['onTrack', 'atRisk', 'offTrack'], 'Status update health'),\n id: stringSchema('Status update ID'),\n initiative: stringSchema('Initiative name or ID'),\n isDiffHidden: booleanSchema('Hide diff with previous update'),\n project: stringSchema('Project name, ID, or slug'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n },\n ['type'],\n ),\n }),\n tool({\n id: 'create_issue_label',\n category: 'issues',\n description: 'Create a new Linear issue label.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n color: stringSchema('Hex color code'),\n description: stringSchema('Label description'),\n isGroup: booleanSchema('Is label group'),\n name: stringSchema('Label name'),\n parent: stringSchema('Parent label group name'),\n teamId: stringSchema('Team UUID'),\n },\n ['name'],\n ),\n }),\n tool({\n id: 'delete_comment',\n category: 'comments',\n description: 'Delete a Linear comment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema({id: stringSchema('Comment ID')}, ['id']),\n }),\n tool({\n id: 'delete_status_update',\n category: 'projects',\n description: 'Delete or archive a Linear project or initiative status update.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n id: stringSchema('Status update ID'),\n type: enumSchema(['project', 'initiative'], 'Status update type'),\n },\n ['id', 'type'],\n ),\n }),\n tool({\n id: 'delete_attachment',\n category: 'attachments',\n description: 'Delete a Linear attachment.',\n sensitivity: 'write',\n sensitive: true,\n requiredScope: 'write',\n inputSchema: objectSchema({id: stringSchema('Attachment ID')}, ['id']),\n }),\n] as const satisfies readonly LinearAgentToolCatalogEntry[];\n\nexport type LinearAgentToolId = (typeof linearAgentToolCatalog)[number]['id'];\n\nexport const linearAgentToolSelectionCatalog =\n buildLinearAgentToolSelectionCatalog(linearAgentToolCatalog);\n\nfunction buildLinearAgentToolSelectionCatalog(\n catalog: readonly LinearAgentToolCatalogEntry[],\n): AgentToolSelectionCatalog {\n return {\n selectors: catalog.map(\n (entry): AgentToolSelector => ({\n token: entry.id,\n kind: 'standalone',\n sensitivity: entry.sensitivity,\n sensitive: entry.sensitive,\n }),\n ),\n };\n}\n\nfunction tool(input: LinearAgentToolCatalogInput): LinearAgentToolCatalogEntry {\n return input;\n}\n\nfunction objectSchema(\n properties: Record<string, AgentToolJsonSchema>,\n required: string[] = [],\n extraSchema: Partial<AgentToolJsonSchema> = {},\n): AgentToolJsonSchema {\n return {\n type: 'object',\n additionalProperties: false,\n properties,\n ...(required.length > 0 ? {required} : {}),\n ...extraSchema,\n };\n}\n\nfunction stringSchema(description?: string): AgentToolJsonSchema {\n return {type: 'string', ...(description ? {description} : {})};\n}\n\nfunction numberSchema(description?: string): AgentToolJsonSchema {\n return {type: 'number', ...(description ? {description} : {})};\n}\n\nfunction booleanSchema(description: string): AgentToolJsonSchema {\n return {type: 'boolean', description};\n}\n\nfunction enumSchema(values: string[], description: string): AgentToolJsonSchema {\n return {type: 'string', description, enum: values};\n}\n\nfunction arraySchema(items: AgentToolJsonSchema): AgentToolJsonSchema {\n return {type: 'array', items};\n}\n\nfunction nullableSchema(schema: AgentToolJsonSchema): AgentToolJsonSchema {\n return {anyOf: [schema, {type: 'null'}]};\n}\n"],"names":["orderBySchema","enumSchema","cursorSchema","stringSchema","limitSchema","numberSchema","dateFilterSchema","prioritySchema","nullableStringSchema","nullableSchema","pageProperties","cursor","limit","orderBy","timelineFilterProperties","createdAt","updatedAt","linearAgentToolCatalog","tool","id","category","description","sensitivity","sensitive","requiredScope","inputSchema","objectSchema","urlOrId","resolved","booleanSchema","threadId","includeCustomerNeeds","includeRelations","includeReleases","assignee","cycle","delegate","includeArchived","label","parentId","priority","project","query","release","state","team","documentId","initiativeId","issueId","milestoneId","projectId","name","includeMembers","includeMilestones","initiative","member","includeResources","includeReleaseNotes","teamId","type","creatorId","user","includeContent","pipeline","includeStages","includeTeams","isProduction","hasReleaseNotes","stage","stageType","version","owner","repo","status","markdown","page","base64Content","contentType","filename","issue","sha256","size","subtitle","title","assetUrl","addReleases","arraySchema","blockedBy","blocks","dueDate","duplicateOf","estimate","labels","links","url","milestone","relatedTo","removeBlockedBy","removeBlocks","removeRelatedTo","removeReleases","setReleases","body","addInitiatives","addTeams","color","icon","lead","removeInitiatives","removeTeams","setInitiatives","setTeams","startDate","startDateResolution","summary","targetDate","targetDateResolution","content","commitSha","completedAt","startedAt","rangeFromRelease","rangeToRelease","releases","health","isDiffHidden","isGroup","parent","linearAgentToolSelectionCatalog","buildLinearAgentToolSelectionCatalog","catalog","selectors","map","entry","token","kind","input","properties","required","extraSchema","additionalProperties","length","values","enum","items","schema","anyOf"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { IntegrationProviderError } from '@shipfox/api-integration-core-dto';
1
+ import { IntegrationProviderError } from '@shipfox/api-integration-spi';
2
2
  export declare class LinearIntegrationProviderError extends IntegrationProviderError {
3
3
  }
4
4
  export declare class LinearInstallStateError extends Error {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAAC,MAAM,mCAAmC,CAAC;AAE3E,qBAAa,8BAA+B,SAAQ,wBAAwB;CAAG;AAE/E,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,SAAiC;CAIrD;AAED,qBAAa,oCAAqC,SAAQ,KAAK;;CAK9D;AAED,qBAAa,wBAAyB,SAAQ,KAAK;aAE/B,aAAa,EAAE,MAAM;aACrB,mBAAmB,EAAE,MAAM,GAAG,SAAS;gBADvC,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,GAAG,SAAS;CAK1D;AAED,qBAAa,qCAAsC,SAAQ,KAAK;aAClC,aAAa,EAAE,MAAM,EAAE;gBAAvB,aAAa,EAAE,MAAM,EAAE;CAIpD;AAED,qBAAa,oCAAqC,SAAQ,KAAK;gBACjD,cAAc,EAAE,MAAM;CAInC;AAED,qBAAa,kCAAmC,SAAQ,KAAK;gBAC/C,YAAY,EAAE,MAAM;CAMjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,YAAY,EAAE,MAAM;CAIjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,YAAY,EAAE,MAAM;CAIjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;aAC1B,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAIjD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAAC,MAAM,8BAA8B,CAAC;AAEtE,qBAAa,8BAA+B,SAAQ,wBAAwB;CAAG;AAE/E,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,SAAiC;CAIrD;AAED,qBAAa,oCAAqC,SAAQ,KAAK;;CAK9D;AAED,qBAAa,wBAAyB,SAAQ,KAAK;aAE/B,aAAa,EAAE,MAAM;aACrB,mBAAmB,EAAE,MAAM,GAAG,SAAS;gBADvC,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,GAAG,SAAS;CAK1D;AAED,qBAAa,qCAAsC,SAAQ,KAAK;aAClC,aAAa,EAAE,MAAM,EAAE;gBAAvB,aAAa,EAAE,MAAM,EAAE;CAIpD;AAED,qBAAa,oCAAqC,SAAQ,KAAK;gBACjD,cAAc,EAAE,MAAM;CAInC;AAED,qBAAa,kCAAmC,SAAQ,KAAK;gBAC/C,YAAY,EAAE,MAAM;CAMjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,YAAY,EAAE,MAAM;CAIjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,YAAY,EAAE,MAAM;CAIjC;AAED,qBAAa,6BAA8B,SAAQ,KAAK;aAC1B,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAIjD"}
@@ -1,4 +1,4 @@
1
- import { IntegrationProviderError } from '@shipfox/api-integration-core-dto';
1
+ import { IntegrationProviderError } from '@shipfox/api-integration-spi';
2
2
  export class LinearIntegrationProviderError extends IntegrationProviderError {
3
3
  }
4
4
  export class LinearInstallStateError extends Error {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["import {IntegrationProviderError} from '@shipfox/api-integration-core-dto';\n\nexport class LinearIntegrationProviderError extends IntegrationProviderError {}\n\nexport class LinearInstallStateError extends Error {\n constructor(message = 'Invalid Linear install state') {\n super(message);\n this.name = 'LinearInstallStateError';\n }\n}\n\nexport class LinearInstallStateActorMismatchError extends Error {\n constructor() {\n super('Linear install state was created by a different user');\n this.name = 'LinearInstallStateActorMismatchError';\n }\n}\n\nexport class LinearOAuthCallbackError extends Error {\n constructor(\n public readonly providerError: string,\n public readonly providerDescription: string | undefined,\n ) {\n super(providerDescription ?? `Linear OAuth callback failed: ${providerError}`);\n this.name = 'LinearOAuthCallbackError';\n }\n}\n\nexport class LinearAuthorizationScopeMismatchError extends Error {\n constructor(public readonly missingScopes: string[]) {\n super(`Linear authorization is missing required scopes: ${missingScopes.join(', ')}`);\n this.name = 'LinearAuthorizationScopeMismatchError';\n }\n}\n\nexport class LinearInstallationAlreadyLinkedError extends Error {\n constructor(organizationId: string) {\n super(`Linear organization is already linked to another Shipfox workspace: ${organizationId}`);\n this.name = 'LinearInstallationAlreadyLinkedError';\n }\n}\n\nexport class LinearConnectionAlreadyLinkedError extends Error {\n constructor(connectionId: string) {\n super(\n `Integration connection is already linked to another Linear organization: ${connectionId}`,\n );\n this.name = 'LinearConnectionAlreadyLinkedError';\n }\n}\n\nexport class LinearConnectionNotFoundError extends Error {\n constructor(connectionId: string) {\n super(`Linear integration connection was not found: ${connectionId}`);\n this.name = 'LinearConnectionNotFoundError';\n }\n}\n\nexport class LinearAccessTokenMissingError extends Error {\n constructor(connectionId: string) {\n super(`Linear access token is missing for connection: ${connectionId}`);\n this.name = 'LinearAccessTokenMissingError';\n }\n}\n\nexport class LinearTokenUnrefreshableError extends Error {\n constructor(public readonly connectionId: string) {\n super(`Linear token cannot be refreshed; reconnect is required: ${connectionId}`);\n this.name = 'LinearTokenUnrefreshableError';\n }\n}\n"],"names":["IntegrationProviderError","LinearIntegrationProviderError","LinearInstallStateError","Error","message","name","LinearInstallStateActorMismatchError","LinearOAuthCallbackError","providerError","providerDescription","LinearAuthorizationScopeMismatchError","missingScopes","join","LinearInstallationAlreadyLinkedError","organizationId","LinearConnectionAlreadyLinkedError","connectionId","LinearConnectionNotFoundError","LinearAccessTokenMissingError","LinearTokenUnrefreshableError"],"mappings":"AAAA,SAAQA,wBAAwB,QAAO,oCAAoC;AAE3E,OAAO,MAAMC,uCAAuCD;AAA0B;AAE9E,OAAO,MAAME,gCAAgCC;IAC3C,YAAYC,UAAU,8BAA8B,CAAE;QACpD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMC,6CAA6CH;IACxD,aAAc;QACZ,KAAK,CAAC;QACN,IAAI,CAACE,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAME,iCAAiCJ;IAC5C,YACE,AAAgBK,aAAqB,EACrC,AAAgBC,mBAAuC,CACvD;QACA,KAAK,CAACA,uBAAuB,CAAC,8BAA8B,EAAED,eAAe,QAH7DA,gBAAAA,oBACAC,sBAAAA;QAGhB,IAAI,CAACJ,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMK,8CAA8CP;IACzD,YAAY,AAAgBQ,aAAuB,CAAE;QACnD,KAAK,CAAC,CAAC,iDAAiD,EAAEA,cAAcC,IAAI,CAAC,OAAO,QAD1DD,gBAAAA;QAE1B,IAAI,CAACN,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMQ,6CAA6CV;IACxD,YAAYW,cAAsB,CAAE;QAClC,KAAK,CAAC,CAAC,oEAAoE,EAAEA,gBAAgB;QAC7F,IAAI,CAACT,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMU,2CAA2CZ;IACtD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CACH,CAAC,yEAAyE,EAAEA,cAAc;QAE5F,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMY,sCAAsCd;IACjD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CAAC,CAAC,6CAA6C,EAAEA,cAAc;QACpE,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMa,sCAAsCf;IACjD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CAAC,CAAC,+CAA+C,EAAEA,cAAc;QACtE,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMc,sCAAsChB;IACjD,YAAY,AAAgBa,YAAoB,CAAE;QAChD,KAAK,CAAC,CAAC,yDAAyD,EAAEA,cAAc,QADtDA,eAAAA;QAE1B,IAAI,CAACX,IAAI,GAAG;IACd;AACF"}
1
+ {"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["import {IntegrationProviderError} from '@shipfox/api-integration-spi';\n\nexport class LinearIntegrationProviderError extends IntegrationProviderError {}\n\nexport class LinearInstallStateError extends Error {\n constructor(message = 'Invalid Linear install state') {\n super(message);\n this.name = 'LinearInstallStateError';\n }\n}\n\nexport class LinearInstallStateActorMismatchError extends Error {\n constructor() {\n super('Linear install state was created by a different user');\n this.name = 'LinearInstallStateActorMismatchError';\n }\n}\n\nexport class LinearOAuthCallbackError extends Error {\n constructor(\n public readonly providerError: string,\n public readonly providerDescription: string | undefined,\n ) {\n super(providerDescription ?? `Linear OAuth callback failed: ${providerError}`);\n this.name = 'LinearOAuthCallbackError';\n }\n}\n\nexport class LinearAuthorizationScopeMismatchError extends Error {\n constructor(public readonly missingScopes: string[]) {\n super(`Linear authorization is missing required scopes: ${missingScopes.join(', ')}`);\n this.name = 'LinearAuthorizationScopeMismatchError';\n }\n}\n\nexport class LinearInstallationAlreadyLinkedError extends Error {\n constructor(organizationId: string) {\n super(`Linear organization is already linked to another Shipfox workspace: ${organizationId}`);\n this.name = 'LinearInstallationAlreadyLinkedError';\n }\n}\n\nexport class LinearConnectionAlreadyLinkedError extends Error {\n constructor(connectionId: string) {\n super(\n `Integration connection is already linked to another Linear organization: ${connectionId}`,\n );\n this.name = 'LinearConnectionAlreadyLinkedError';\n }\n}\n\nexport class LinearConnectionNotFoundError extends Error {\n constructor(connectionId: string) {\n super(`Linear integration connection was not found: ${connectionId}`);\n this.name = 'LinearConnectionNotFoundError';\n }\n}\n\nexport class LinearAccessTokenMissingError extends Error {\n constructor(connectionId: string) {\n super(`Linear access token is missing for connection: ${connectionId}`);\n this.name = 'LinearAccessTokenMissingError';\n }\n}\n\nexport class LinearTokenUnrefreshableError extends Error {\n constructor(public readonly connectionId: string) {\n super(`Linear token cannot be refreshed; reconnect is required: ${connectionId}`);\n this.name = 'LinearTokenUnrefreshableError';\n }\n}\n"],"names":["IntegrationProviderError","LinearIntegrationProviderError","LinearInstallStateError","Error","message","name","LinearInstallStateActorMismatchError","LinearOAuthCallbackError","providerError","providerDescription","LinearAuthorizationScopeMismatchError","missingScopes","join","LinearInstallationAlreadyLinkedError","organizationId","LinearConnectionAlreadyLinkedError","connectionId","LinearConnectionNotFoundError","LinearAccessTokenMissingError","LinearTokenUnrefreshableError"],"mappings":"AAAA,SAAQA,wBAAwB,QAAO,+BAA+B;AAEtE,OAAO,MAAMC,uCAAuCD;AAA0B;AAE9E,OAAO,MAAME,gCAAgCC;IAC3C,YAAYC,UAAU,8BAA8B,CAAE;QACpD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMC,6CAA6CH;IACxD,aAAc;QACZ,KAAK,CAAC;QACN,IAAI,CAACE,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAME,iCAAiCJ;IAC5C,YACE,AAAgBK,aAAqB,EACrC,AAAgBC,mBAAuC,CACvD;QACA,KAAK,CAACA,uBAAuB,CAAC,8BAA8B,EAAED,eAAe,QAH7DA,gBAAAA,oBACAC,sBAAAA;QAGhB,IAAI,CAACJ,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMK,8CAA8CP;IACzD,YAAY,AAAgBQ,aAAuB,CAAE;QACnD,KAAK,CAAC,CAAC,iDAAiD,EAAEA,cAAcC,IAAI,CAAC,OAAO,QAD1DD,gBAAAA;QAE1B,IAAI,CAACN,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMQ,6CAA6CV;IACxD,YAAYW,cAAsB,CAAE;QAClC,KAAK,CAAC,CAAC,oEAAoE,EAAEA,gBAAgB;QAC7F,IAAI,CAACT,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMU,2CAA2CZ;IACtD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CACH,CAAC,yEAAyE,EAAEA,cAAc;QAE5F,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMY,sCAAsCd;IACjD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CAAC,CAAC,6CAA6C,EAAEA,cAAc;QACpE,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMa,sCAAsCf;IACjD,YAAYa,YAAoB,CAAE;QAChC,KAAK,CAAC,CAAC,+CAA+C,EAAEA,cAAc;QACtE,IAAI,CAACX,IAAI,GAAG;IACd;AACF;AAEA,OAAO,MAAMc,sCAAsChB;IACjD,YAAY,AAAgBa,YAAoB,CAAE;QAChD,KAAK,CAAC,CAAC,yDAAyD,EAAEA,cAAc,QADtDA,eAAAA;QAE1B,IAAI,CAACX,IAAI,GAAG;IACd;AACF"}
@@ -1,5 +1,5 @@
1
1
  import type { UserContextMembership } from '@shipfox/api-auth-context';
2
- import type { IntegrationConnection } from '@shipfox/api-integration-core-dto';
2
+ import type { IntegrationConnection } from '@shipfox/api-integration-spi';
3
3
  import type { LinearApiClient } from '#api/client.js';
4
4
  import type { LinearTokenStore } from '#core/tokens.js';
5
5
  export interface ConnectLinearInstallationInput {
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/core/install.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mCAAmC,CAAC;AAE7E,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAStD,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACzD,0BAA0B,EAAE,CAAC,MAAM,EAAE;QACnC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;KACnD,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,2BAA2B,EAAE,CAAC,KAAK,EAAE;QACnC,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CACzB,KAAK,EAAE,8BAA8B,KAClC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,4BAA4B,EAAE,CAAC,KAAK,EAAE;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAuD1C;AAED,wBAAsB,8BAA8B,CAAC,MAAM,EAAE;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACzD,0BAA0B,EAAE,CAAC,KAAK,EAAE;QAClC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;KACnD,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB,GAAG,OAAO,CAAC,KAAK,CAAC,CASjB"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/core/install.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAStD,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACzD,0BAA0B,EAAE,CAAC,MAAM,EAAE;QACnC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;KACnD,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,2BAA2B,EAAE,CAAC,KAAK,EAAE;QACnC,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CACzB,KAAK,EAAE,8BAA8B,KAClC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,4BAA4B,EAAE,CAAC,KAAK,EAAE;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAuD1C;AAED,wBAAsB,8BAA8B,CAAC,MAAM,EAAE;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACzD,0BAA0B,EAAE,CAAC,KAAK,EAAE;QAClC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;KACnD,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB,GAAG,OAAO,CAAC,KAAK,CAAC,CASjB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/install.ts"],"sourcesContent":["import type {UserContextMembership} from '@shipfox/api-auth-context';\nimport type {IntegrationConnection} from '@shipfox/api-integration-core-dto';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {LinearApiClient} from '#api/client.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\nimport {\n LinearInstallationAlreadyLinkedError,\n LinearInstallStateActorMismatchError,\n LinearOAuthCallbackError,\n} from './errors.js';\nimport {assertLinearAuthorizationScopes} from './scopes.js';\nimport {verifyLinearInstallState} from './state.js';\n\nexport interface ConnectLinearInstallationInput {\n workspaceId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt: Date | null;\n displayName: string;\n}\n\nexport interface HandleLinearCallbackParams {\n linear: LinearApiClient;\n tokenStore: Pick<LinearTokenStore, 'storeTokens'>;\n code: string;\n state: string;\n sessionUserId: string;\n sessionMemberships: ReadonlyArray<UserContextMembership>;\n requireWorkspaceMembership: (params: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<UserContextMembership>;\n }) => Promise<unknown>;\n getExistingLinearConnection: (input: {\n organizationId: string;\n }) => Promise<IntegrationConnection<'linear'> | undefined>;\n connectLinearInstallation: (\n input: ConnectLinearInstallationInput,\n ) => Promise<IntegrationConnection<'linear'>>;\n disconnectLinearInstallation: (input: {connectionId: string}) => Promise<void>;\n}\n\nexport async function handleLinearCallback(\n params: HandleLinearCallbackParams,\n): Promise<IntegrationConnection<'linear'>> {\n if (typeof params.disconnectLinearInstallation !== 'function') {\n throw new Error('Linear installation cleanup is not configured');\n }\n\n const claims = verifyLinearInstallState(params.state);\n if (claims.userId !== params.sessionUserId) {\n throw new LinearInstallStateActorMismatchError();\n }\n await params.requireWorkspaceMembership({\n workspaceId: claims.workspaceId,\n userId: claims.userId,\n memberships: params.sessionMemberships,\n });\n\n const authorization = await params.linear.exchangeAuthorizationCode({code: params.code});\n let connectedConnectionId: string | undefined;\n let shouldDisconnectConnection = false;\n try {\n const identity = await params.linear.getIdentity({accessToken: authorization.accessToken});\n const existing = await params.getExistingLinearConnection({\n organizationId: identity.organizationId,\n });\n if (existing && existing.workspaceId !== claims.workspaceId) {\n throw new LinearInstallationAlreadyLinkedError(identity.organizationId);\n }\n\n assertLinearAuthorizationScopes(authorization.scopes);\n\n const connection = await params.connectLinearInstallation({\n workspaceId: claims.workspaceId,\n organizationId: identity.organizationId,\n organizationUrlKey: identity.organizationUrlKey,\n appUserId: identity.appUserId,\n scopes: authorization.scopes,\n tokenExpiresAt: authorization.expiresAt ?? null,\n displayName: `Linear ${identity.organizationName}`,\n });\n connectedConnectionId = connection.id;\n shouldDisconnectConnection = !existing;\n await params.tokenStore.storeTokens({\n connectionId: connection.id,\n accessToken: authorization.accessToken,\n refreshToken: authorization.refreshToken,\n editedBy: claims.userId,\n });\n\n return connection;\n } catch (error) {\n await bestEffortRevokeAuthorization(params.linear, authorization);\n if (connectedConnectionId && shouldDisconnectConnection) {\n await bestEffortDisconnectLinearInstallation(params, connectedConnectionId);\n }\n throw error;\n }\n}\n\nexport async function handleLinearOAuthCallbackError(params: {\n state: string;\n error: string;\n errorDescription?: string | undefined;\n sessionUserId: string;\n sessionMemberships: ReadonlyArray<UserContextMembership>;\n requireWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<UserContextMembership>;\n }) => Promise<unknown>;\n}): Promise<never> {\n const claims = verifyLinearInstallState(params.state);\n if (claims.userId !== params.sessionUserId) throw new LinearInstallStateActorMismatchError();\n await params.requireWorkspaceMembership({\n workspaceId: claims.workspaceId,\n userId: claims.userId,\n memberships: params.sessionMemberships,\n });\n throw new LinearOAuthCallbackError(params.error, params.errorDescription);\n}\n\nasync function bestEffortRevokeAuthorization(\n linear: LinearApiClient,\n authorization: {accessToken: string; refreshToken?: string | undefined},\n): Promise<void> {\n await Promise.all([\n authorization.refreshToken\n ? revokeToken(linear, authorization.refreshToken, 'refresh_token')\n : Promise.resolve(),\n revokeToken(linear, authorization.accessToken, 'access_token'),\n ]);\n}\n\nasync function revokeToken(\n linear: LinearApiClient,\n token: string,\n tokenTypeHint: 'access_token' | 'refresh_token',\n): Promise<void> {\n try {\n await linear.revokeToken({token, tokenTypeHint});\n } catch (error) {\n logger().warn({err: error, tokenTypeHint}, 'Linear OAuth token revocation failed');\n }\n}\n\nasync function bestEffortDisconnectLinearInstallation(\n params: HandleLinearCallbackParams,\n connectionId: string,\n): Promise<void> {\n try {\n await params.disconnectLinearInstallation({connectionId});\n } catch (error) {\n logger().warn(\n {err: error, connectionId},\n 'Linear connect compensation failed after token storage rejection',\n );\n }\n}\n"],"names":["logger","LinearInstallationAlreadyLinkedError","LinearInstallStateActorMismatchError","LinearOAuthCallbackError","assertLinearAuthorizationScopes","verifyLinearInstallState","handleLinearCallback","params","disconnectLinearInstallation","Error","claims","state","userId","sessionUserId","requireWorkspaceMembership","workspaceId","memberships","sessionMemberships","authorization","linear","exchangeAuthorizationCode","code","connectedConnectionId","shouldDisconnectConnection","identity","getIdentity","accessToken","existing","getExistingLinearConnection","organizationId","scopes","connection","connectLinearInstallation","organizationUrlKey","appUserId","tokenExpiresAt","expiresAt","displayName","organizationName","id","tokenStore","storeTokens","connectionId","refreshToken","editedBy","error","bestEffortRevokeAuthorization","bestEffortDisconnectLinearInstallation","handleLinearOAuthCallbackError","errorDescription","Promise","all","revokeToken","resolve","token","tokenTypeHint","warn","err"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/install.ts"],"sourcesContent":["import type {UserContextMembership} from '@shipfox/api-auth-context';\nimport type {IntegrationConnection} from '@shipfox/api-integration-spi';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {LinearApiClient} from '#api/client.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\nimport {\n LinearInstallationAlreadyLinkedError,\n LinearInstallStateActorMismatchError,\n LinearOAuthCallbackError,\n} from './errors.js';\nimport {assertLinearAuthorizationScopes} from './scopes.js';\nimport {verifyLinearInstallState} from './state.js';\n\nexport interface ConnectLinearInstallationInput {\n workspaceId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt: Date | null;\n displayName: string;\n}\n\nexport interface HandleLinearCallbackParams {\n linear: LinearApiClient;\n tokenStore: Pick<LinearTokenStore, 'storeTokens'>;\n code: string;\n state: string;\n sessionUserId: string;\n sessionMemberships: ReadonlyArray<UserContextMembership>;\n requireWorkspaceMembership: (params: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<UserContextMembership>;\n }) => Promise<unknown>;\n getExistingLinearConnection: (input: {\n organizationId: string;\n }) => Promise<IntegrationConnection<'linear'> | undefined>;\n connectLinearInstallation: (\n input: ConnectLinearInstallationInput,\n ) => Promise<IntegrationConnection<'linear'>>;\n disconnectLinearInstallation: (input: {connectionId: string}) => Promise<void>;\n}\n\nexport async function handleLinearCallback(\n params: HandleLinearCallbackParams,\n): Promise<IntegrationConnection<'linear'>> {\n if (typeof params.disconnectLinearInstallation !== 'function') {\n throw new Error('Linear installation cleanup is not configured');\n }\n\n const claims = verifyLinearInstallState(params.state);\n if (claims.userId !== params.sessionUserId) {\n throw new LinearInstallStateActorMismatchError();\n }\n await params.requireWorkspaceMembership({\n workspaceId: claims.workspaceId,\n userId: claims.userId,\n memberships: params.sessionMemberships,\n });\n\n const authorization = await params.linear.exchangeAuthorizationCode({code: params.code});\n let connectedConnectionId: string | undefined;\n let shouldDisconnectConnection = false;\n try {\n const identity = await params.linear.getIdentity({accessToken: authorization.accessToken});\n const existing = await params.getExistingLinearConnection({\n organizationId: identity.organizationId,\n });\n if (existing && existing.workspaceId !== claims.workspaceId) {\n throw new LinearInstallationAlreadyLinkedError(identity.organizationId);\n }\n\n assertLinearAuthorizationScopes(authorization.scopes);\n\n const connection = await params.connectLinearInstallation({\n workspaceId: claims.workspaceId,\n organizationId: identity.organizationId,\n organizationUrlKey: identity.organizationUrlKey,\n appUserId: identity.appUserId,\n scopes: authorization.scopes,\n tokenExpiresAt: authorization.expiresAt ?? null,\n displayName: `Linear ${identity.organizationName}`,\n });\n connectedConnectionId = connection.id;\n shouldDisconnectConnection = !existing;\n await params.tokenStore.storeTokens({\n connectionId: connection.id,\n accessToken: authorization.accessToken,\n refreshToken: authorization.refreshToken,\n editedBy: claims.userId,\n });\n\n return connection;\n } catch (error) {\n await bestEffortRevokeAuthorization(params.linear, authorization);\n if (connectedConnectionId && shouldDisconnectConnection) {\n await bestEffortDisconnectLinearInstallation(params, connectedConnectionId);\n }\n throw error;\n }\n}\n\nexport async function handleLinearOAuthCallbackError(params: {\n state: string;\n error: string;\n errorDescription?: string | undefined;\n sessionUserId: string;\n sessionMemberships: ReadonlyArray<UserContextMembership>;\n requireWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<UserContextMembership>;\n }) => Promise<unknown>;\n}): Promise<never> {\n const claims = verifyLinearInstallState(params.state);\n if (claims.userId !== params.sessionUserId) throw new LinearInstallStateActorMismatchError();\n await params.requireWorkspaceMembership({\n workspaceId: claims.workspaceId,\n userId: claims.userId,\n memberships: params.sessionMemberships,\n });\n throw new LinearOAuthCallbackError(params.error, params.errorDescription);\n}\n\nasync function bestEffortRevokeAuthorization(\n linear: LinearApiClient,\n authorization: {accessToken: string; refreshToken?: string | undefined},\n): Promise<void> {\n await Promise.all([\n authorization.refreshToken\n ? revokeToken(linear, authorization.refreshToken, 'refresh_token')\n : Promise.resolve(),\n revokeToken(linear, authorization.accessToken, 'access_token'),\n ]);\n}\n\nasync function revokeToken(\n linear: LinearApiClient,\n token: string,\n tokenTypeHint: 'access_token' | 'refresh_token',\n): Promise<void> {\n try {\n await linear.revokeToken({token, tokenTypeHint});\n } catch (error) {\n logger().warn({err: error, tokenTypeHint}, 'Linear OAuth token revocation failed');\n }\n}\n\nasync function bestEffortDisconnectLinearInstallation(\n params: HandleLinearCallbackParams,\n connectionId: string,\n): Promise<void> {\n try {\n await params.disconnectLinearInstallation({connectionId});\n } catch (error) {\n logger().warn(\n {err: error, connectionId},\n 'Linear connect compensation failed after token storage rejection',\n );\n }\n}\n"],"names":["logger","LinearInstallationAlreadyLinkedError","LinearInstallStateActorMismatchError","LinearOAuthCallbackError","assertLinearAuthorizationScopes","verifyLinearInstallState","handleLinearCallback","params","disconnectLinearInstallation","Error","claims","state","userId","sessionUserId","requireWorkspaceMembership","workspaceId","memberships","sessionMemberships","authorization","linear","exchangeAuthorizationCode","code","connectedConnectionId","shouldDisconnectConnection","identity","getIdentity","accessToken","existing","getExistingLinearConnection","organizationId","scopes","connection","connectLinearInstallation","organizationUrlKey","appUserId","tokenExpiresAt","expiresAt","displayName","organizationName","id","tokenStore","storeTokens","connectionId","refreshToken","editedBy","error","bestEffortRevokeAuthorization","bestEffortDisconnectLinearInstallation","handleLinearOAuthCallbackError","errorDescription","Promise","all","revokeToken","resolve","token","tokenTypeHint","warn","err"],"mappings":"AAEA,SAAQA,MAAM,QAAO,8BAA8B;AAGnD,SACEC,oCAAoC,EACpCC,oCAAoC,EACpCC,wBAAwB,QACnB,cAAc;AACrB,SAAQC,+BAA+B,QAAO,cAAc;AAC5D,SAAQC,wBAAwB,QAAO,aAAa;AAiCpD,OAAO,eAAeC,qBACpBC,MAAkC;IAElC,IAAI,OAAOA,OAAOC,4BAA4B,KAAK,YAAY;QAC7D,MAAM,IAAIC,MAAM;IAClB;IAEA,MAAMC,SAASL,yBAAyBE,OAAOI,KAAK;IACpD,IAAID,OAAOE,MAAM,KAAKL,OAAOM,aAAa,EAAE;QAC1C,MAAM,IAAIX;IACZ;IACA,MAAMK,OAAOO,0BAA0B,CAAC;QACtCC,aAAaL,OAAOK,WAAW;QAC/BH,QAAQF,OAAOE,MAAM;QACrBI,aAAaT,OAAOU,kBAAkB;IACxC;IAEA,MAAMC,gBAAgB,MAAMX,OAAOY,MAAM,CAACC,yBAAyB,CAAC;QAACC,MAAMd,OAAOc,IAAI;IAAA;IACtF,IAAIC;IACJ,IAAIC,6BAA6B;IACjC,IAAI;QACF,MAAMC,WAAW,MAAMjB,OAAOY,MAAM,CAACM,WAAW,CAAC;YAACC,aAAaR,cAAcQ,WAAW;QAAA;QACxF,MAAMC,WAAW,MAAMpB,OAAOqB,2BAA2B,CAAC;YACxDC,gBAAgBL,SAASK,cAAc;QACzC;QACA,IAAIF,YAAYA,SAASZ,WAAW,KAAKL,OAAOK,WAAW,EAAE;YAC3D,MAAM,IAAId,qCAAqCuB,SAASK,cAAc;QACxE;QAEAzB,gCAAgCc,cAAcY,MAAM;QAEpD,MAAMC,aAAa,MAAMxB,OAAOyB,yBAAyB,CAAC;YACxDjB,aAAaL,OAAOK,WAAW;YAC/Bc,gBAAgBL,SAASK,cAAc;YACvCI,oBAAoBT,SAASS,kBAAkB;YAC/CC,WAAWV,SAASU,SAAS;YAC7BJ,QAAQZ,cAAcY,MAAM;YAC5BK,gBAAgBjB,cAAckB,SAAS,IAAI;YAC3CC,aAAa,CAAC,OAAO,EAAEb,SAASc,gBAAgB,EAAE;QACpD;QACAhB,wBAAwBS,WAAWQ,EAAE;QACrChB,6BAA6B,CAACI;QAC9B,MAAMpB,OAAOiC,UAAU,CAACC,WAAW,CAAC;YAClCC,cAAcX,WAAWQ,EAAE;YAC3Bb,aAAaR,cAAcQ,WAAW;YACtCiB,cAAczB,cAAcyB,YAAY;YACxCC,UAAUlC,OAAOE,MAAM;QACzB;QAEA,OAAOmB;IACT,EAAE,OAAOc,OAAO;QACd,MAAMC,8BAA8BvC,OAAOY,MAAM,EAAED;QACnD,IAAII,yBAAyBC,4BAA4B;YACvD,MAAMwB,uCAAuCxC,QAAQe;QACvD;QACA,MAAMuB;IACR;AACF;AAEA,OAAO,eAAeG,+BAA+BzC,MAWpD;IACC,MAAMG,SAASL,yBAAyBE,OAAOI,KAAK;IACpD,IAAID,OAAOE,MAAM,KAAKL,OAAOM,aAAa,EAAE,MAAM,IAAIX;IACtD,MAAMK,OAAOO,0BAA0B,CAAC;QACtCC,aAAaL,OAAOK,WAAW;QAC/BH,QAAQF,OAAOE,MAAM;QACrBI,aAAaT,OAAOU,kBAAkB;IACxC;IACA,MAAM,IAAId,yBAAyBI,OAAOsC,KAAK,EAAEtC,OAAO0C,gBAAgB;AAC1E;AAEA,eAAeH,8BACb3B,MAAuB,EACvBD,aAAuE;IAEvE,MAAMgC,QAAQC,GAAG,CAAC;QAChBjC,cAAcyB,YAAY,GACtBS,YAAYjC,QAAQD,cAAcyB,YAAY,EAAE,mBAChDO,QAAQG,OAAO;QACnBD,YAAYjC,QAAQD,cAAcQ,WAAW,EAAE;KAChD;AACH;AAEA,eAAe0B,YACbjC,MAAuB,EACvBmC,KAAa,EACbC,aAA+C;IAE/C,IAAI;QACF,MAAMpC,OAAOiC,WAAW,CAAC;YAACE;YAAOC;QAAa;IAChD,EAAE,OAAOV,OAAO;QACd7C,SAASwD,IAAI,CAAC;YAACC,KAAKZ;YAAOU;QAAa,GAAG;IAC7C;AACF;AAEA,eAAeR,uCACbxC,MAAkC,EAClCmC,YAAoB;IAEpB,IAAI;QACF,MAAMnC,OAAOC,4BAA4B,CAAC;YAACkC;QAAY;IACzD,EAAE,OAAOG,OAAO;QACd7C,SAASwD,IAAI,CACX;YAACC,KAAKZ;YAAOH;QAAY,GACzB;IAEJ;AACF"}
@@ -1,4 +1,4 @@
1
- import { type GetIntegrationConnectionByIdFn, type PublishIntegrationEventReceivedFn, type RecordDeliveryOnlyFn, type StoredWebhookRequest, type WebhookProcessingResult } from '@shipfox/api-integration-core-dto';
1
+ import { type GetIntegrationConnectionByIdFn, type PublishIntegrationEventReceivedFn, type RecordDeliveryOnlyFn, type StoredWebhookRequest, type WebhookProcessingResult } from '@shipfox/api-integration-spi';
2
2
  import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
3
3
  export interface CreateLinearWebhookProcessorOptions {
4
4
  coreDb: () => NodePgDatabase<Record<string, unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-processor.d.ts","sourceRoot":"","sources":["../../src/core/webhook-processor.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,iCAAiC,EACtC,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,mCAAmC,CAAC;AAO3C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAS9D,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC1E;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mCAAmC,GAC3C,sBAAsB,CAExB"}
1
+ {"version":3,"file":"webhook-processor.d.ts","sourceRoot":"","sources":["../../src/core/webhook-processor.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,iCAAiC,EACtC,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAS9D,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC1E;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mCAAmC,GAC3C,sBAAsB,CAExB"}
@@ -1,6 +1,6 @@
1
1
  import { Buffer } from 'node:buffer';
2
- import { decodeWebhookBody } from '@shipfox/api-integration-core-dto';
3
2
  import { LINEAR_PROVIDER, linearWebhookBaseEnvelopeSchema } from '@shipfox/api-integration-linear-dto';
3
+ import { decodeWebhookBody } from '@shipfox/api-integration-spi';
4
4
  import { verifyHexHmacSignature } from '@shipfox/node-fastify';
5
5
  import { logger } from '@shipfox/node-opentelemetry';
6
6
  import { config } from '#config.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/webhook-processor.ts"],"sourcesContent":["import {Buffer} from 'node:buffer';\nimport {\n decodeWebhookBody,\n type GetIntegrationConnectionByIdFn,\n type PublishIntegrationEventReceivedFn,\n type RecordDeliveryOnlyFn,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n} from '@shipfox/api-integration-core-dto';\nimport {\n LINEAR_PROVIDER,\n linearWebhookBaseEnvelopeSchema,\n} from '@shipfox/api-integration-linear-dto';\nimport {verifyHexHmacSignature} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {config} from '#config.js';\nimport {handleLinearWebhook} from '#core/webhook.js';\n\nconst DELIVERY_HEADER = 'linear-delivery';\nconst EVENT_HEADER = 'linear-event';\nconst SIGNATURE_HEADER = 'linear-signature';\nconst WEBHOOK_REPLAY_WINDOW_MS = 60_000;\n\nexport interface CreateLinearWebhookProcessorOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport interface LinearWebhookProcessor {\n process(request: StoredWebhookRequest): Promise<WebhookProcessingResult>;\n}\n\nexport function createLinearWebhookProcessor(\n options: CreateLinearWebhookProcessorOptions,\n): LinearWebhookProcessor {\n return {process: (request) => processLinearWebhookRequest(options, request)};\n}\n\nasync function processLinearWebhookRequest(\n options: CreateLinearWebhookProcessorOptions,\n request: StoredWebhookRequest,\n): Promise<WebhookProcessingResult> {\n if (request.route_id !== 'linear') {\n throw new Error(`Linear processor cannot process ${request.route_id} requests`);\n }\n\n const deliveryId = request.headers[DELIVERY_HEADER];\n const event = request.headers[EVENT_HEADER];\n const signature = request.headers[SIGNATURE_HEADER];\n if (!deliveryId || !event || !signature) {\n return {outcome: 'discarded', reason: 'missing_required_input'};\n }\n\n const rawBody = Buffer.from(decodeWebhookBody(request.body));\n if (\n !verifyHexHmacSignature({\n rawBody,\n signature,\n secret: config.LINEAR_WEBHOOK_SIGNING_SECRET,\n })\n ) {\n return {outcome: 'discarded', reason: 'invalid_signature', deliveryId};\n }\n\n let rawPayload: unknown;\n try {\n rawPayload = JSON.parse(rawBody.toString('utf8'));\n } catch (error) {\n logger().warn({deliveryId, err: error}, 'linear webhook payload JSON parse failed');\n return {outcome: 'discarded', reason: 'malformed_payload', deliveryId};\n }\n\n const payload = linearWebhookBaseEnvelopeSchema.safeParse(rawPayload);\n if (!payload.success) {\n logger().warn(\n {deliveryId, issues: payload.error.issues},\n 'linear webhook envelope failed schema validation',\n );\n await recordSignedDeliveryOnly(options, deliveryId);\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n\n const receivedAt = new Date(request.received_at).getTime();\n if (Math.abs(receivedAt - payload.data.webhookTimestamp) > WEBHOOK_REPLAY_WINDOW_MS) {\n return {outcome: 'discarded', reason: 'stale_at_receipt', deliveryId};\n }\n\n if (event !== payload.data.type) {\n logger().warn(\n {deliveryId, event, type: payload.data.type},\n 'linear webhook event header did not match payload type',\n );\n await recordSignedDeliveryOnly(options, deliveryId);\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n\n const result = await options.coreDb().transaction(async (tx) =>\n handleLinearWebhook({\n tx,\n deliveryId,\n payload: payload.data,\n rawPayload,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n }),\n );\n\n if (result.outcome === 'published') return {outcome: 'processed', deliveryId};\n if (result.outcome === 'duplicate') return {outcome: 'duplicate', deliveryId};\n if (result.outcome === 'unsupported-event') {\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n return {outcome: 'discarded', reason: 'connection_unavailable', deliveryId};\n}\n\nasync function recordSignedDeliveryOnly(\n options: Pick<CreateLinearWebhookProcessorOptions, 'coreDb' | 'recordDeliveryOnly'>,\n deliveryId: string,\n): Promise<void> {\n await options.coreDb().transaction(async (tx) => {\n await options.recordDeliveryOnly({tx, provider: LINEAR_PROVIDER, deliveryId});\n });\n}\n"],"names":["Buffer","decodeWebhookBody","LINEAR_PROVIDER","linearWebhookBaseEnvelopeSchema","verifyHexHmacSignature","logger","config","handleLinearWebhook","DELIVERY_HEADER","EVENT_HEADER","SIGNATURE_HEADER","WEBHOOK_REPLAY_WINDOW_MS","createLinearWebhookProcessor","options","process","request","processLinearWebhookRequest","route_id","Error","deliveryId","headers","event","signature","outcome","reason","rawBody","from","body","secret","LINEAR_WEBHOOK_SIGNING_SECRET","rawPayload","JSON","parse","toString","error","warn","err","payload","safeParse","success","issues","recordSignedDeliveryOnly","receivedAt","Date","received_at","getTime","Math","abs","data","webhookTimestamp","type","result","coreDb","transaction","tx","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","provider"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/webhook-processor.ts"],"sourcesContent":["import {Buffer} from 'node:buffer';\nimport {\n LINEAR_PROVIDER,\n linearWebhookBaseEnvelopeSchema,\n} from '@shipfox/api-integration-linear-dto';\nimport {\n decodeWebhookBody,\n type GetIntegrationConnectionByIdFn,\n type PublishIntegrationEventReceivedFn,\n type RecordDeliveryOnlyFn,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n} from '@shipfox/api-integration-spi';\nimport {verifyHexHmacSignature} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {config} from '#config.js';\nimport {handleLinearWebhook} from '#core/webhook.js';\n\nconst DELIVERY_HEADER = 'linear-delivery';\nconst EVENT_HEADER = 'linear-event';\nconst SIGNATURE_HEADER = 'linear-signature';\nconst WEBHOOK_REPLAY_WINDOW_MS = 60_000;\n\nexport interface CreateLinearWebhookProcessorOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport interface LinearWebhookProcessor {\n process(request: StoredWebhookRequest): Promise<WebhookProcessingResult>;\n}\n\nexport function createLinearWebhookProcessor(\n options: CreateLinearWebhookProcessorOptions,\n): LinearWebhookProcessor {\n return {process: (request) => processLinearWebhookRequest(options, request)};\n}\n\nasync function processLinearWebhookRequest(\n options: CreateLinearWebhookProcessorOptions,\n request: StoredWebhookRequest,\n): Promise<WebhookProcessingResult> {\n if (request.route_id !== 'linear') {\n throw new Error(`Linear processor cannot process ${request.route_id} requests`);\n }\n\n const deliveryId = request.headers[DELIVERY_HEADER];\n const event = request.headers[EVENT_HEADER];\n const signature = request.headers[SIGNATURE_HEADER];\n if (!deliveryId || !event || !signature) {\n return {outcome: 'discarded', reason: 'missing_required_input'};\n }\n\n const rawBody = Buffer.from(decodeWebhookBody(request.body));\n if (\n !verifyHexHmacSignature({\n rawBody,\n signature,\n secret: config.LINEAR_WEBHOOK_SIGNING_SECRET,\n })\n ) {\n return {outcome: 'discarded', reason: 'invalid_signature', deliveryId};\n }\n\n let rawPayload: unknown;\n try {\n rawPayload = JSON.parse(rawBody.toString('utf8'));\n } catch (error) {\n logger().warn({deliveryId, err: error}, 'linear webhook payload JSON parse failed');\n return {outcome: 'discarded', reason: 'malformed_payload', deliveryId};\n }\n\n const payload = linearWebhookBaseEnvelopeSchema.safeParse(rawPayload);\n if (!payload.success) {\n logger().warn(\n {deliveryId, issues: payload.error.issues},\n 'linear webhook envelope failed schema validation',\n );\n await recordSignedDeliveryOnly(options, deliveryId);\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n\n const receivedAt = new Date(request.received_at).getTime();\n if (Math.abs(receivedAt - payload.data.webhookTimestamp) > WEBHOOK_REPLAY_WINDOW_MS) {\n return {outcome: 'discarded', reason: 'stale_at_receipt', deliveryId};\n }\n\n if (event !== payload.data.type) {\n logger().warn(\n {deliveryId, event, type: payload.data.type},\n 'linear webhook event header did not match payload type',\n );\n await recordSignedDeliveryOnly(options, deliveryId);\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n\n const result = await options.coreDb().transaction(async (tx) =>\n handleLinearWebhook({\n tx,\n deliveryId,\n payload: payload.data,\n rawPayload,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n }),\n );\n\n if (result.outcome === 'published') return {outcome: 'processed', deliveryId};\n if (result.outcome === 'duplicate') return {outcome: 'duplicate', deliveryId};\n if (result.outcome === 'unsupported-event') {\n return {outcome: 'discarded', reason: 'unsupported_event', deliveryId};\n }\n return {outcome: 'discarded', reason: 'connection_unavailable', deliveryId};\n}\n\nasync function recordSignedDeliveryOnly(\n options: Pick<CreateLinearWebhookProcessorOptions, 'coreDb' | 'recordDeliveryOnly'>,\n deliveryId: string,\n): Promise<void> {\n await options.coreDb().transaction(async (tx) => {\n await options.recordDeliveryOnly({tx, provider: LINEAR_PROVIDER, deliveryId});\n });\n}\n"],"names":["Buffer","LINEAR_PROVIDER","linearWebhookBaseEnvelopeSchema","decodeWebhookBody","verifyHexHmacSignature","logger","config","handleLinearWebhook","DELIVERY_HEADER","EVENT_HEADER","SIGNATURE_HEADER","WEBHOOK_REPLAY_WINDOW_MS","createLinearWebhookProcessor","options","process","request","processLinearWebhookRequest","route_id","Error","deliveryId","headers","event","signature","outcome","reason","rawBody","from","body","secret","LINEAR_WEBHOOK_SIGNING_SECRET","rawPayload","JSON","parse","toString","error","warn","err","payload","safeParse","success","issues","recordSignedDeliveryOnly","receivedAt","Date","received_at","getTime","Math","abs","data","webhookTimestamp","type","result","coreDb","transaction","tx","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","provider"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { GetIntegrationConnectionByIdFn, IntegrationTx, PublishIntegrationEventReceivedFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-core-dto';
2
1
  import { type LinearWebhookBaseEnvelopeDto } from '@shipfox/api-integration-linear-dto';
2
+ import type { GetIntegrationConnectionByIdFn, IntegrationTx, PublishIntegrationEventReceivedFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-spi';
3
3
  export interface HandleLinearWebhookParams {
4
4
  tx: IntegrationTx;
5
5
  deliveryId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/core/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,aAAa,EACb,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,4BAA4B,EAIlC,MAAM,qCAAqC,CAAC;AAI7C,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,aAAa,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,4BAA4B,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,MAAM,MAAM,0BAA0B,GAClC,WAAW,GACX,WAAW,GACX,sBAAsB,GACtB,sBAAsB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,mBAAmB,CAAC;AAExB,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC;IAAC,OAAO,EAAE,0BAA0B,CAAA;CAAC,CAAC,CA2FhD"}
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/core/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,4BAA4B,EAIlC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EACV,8BAA8B,EAC9B,aAAa,EACb,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAItC,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,aAAa,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,4BAA4B,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,MAAM,MAAM,0BAA0B,GAClC,WAAW,GACX,WAAW,GACX,sBAAsB,GACtB,sBAAsB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,mBAAmB,CAAC;AAExB,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC;IAAC,OAAO,EAAE,0BAA0B,CAAA;CAAC,CAAC,CA2FhD"}