linear-agent-bridge 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +613 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +19 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/agent/context-builder.d.ts +9 -0
  8. package/dist/src/agent/context-builder.d.ts.map +1 -0
  9. package/dist/src/agent/context-builder.js +121 -0
  10. package/dist/src/agent/context-builder.js.map +1 -0
  11. package/dist/src/agent/plan-manager.d.ts +5 -0
  12. package/dist/src/agent/plan-manager.d.ts.map +1 -0
  13. package/dist/src/agent/plan-manager.js +11 -0
  14. package/dist/src/agent/plan-manager.js.map +1 -0
  15. package/dist/src/agent/response-tracker.d.ts +4 -0
  16. package/dist/src/agent/response-tracker.d.ts.map +1 -0
  17. package/dist/src/agent/response-tracker.js +11 -0
  18. package/dist/src/agent/response-tracker.js.map +1 -0
  19. package/dist/src/agent/session-token.d.ts +5 -0
  20. package/dist/src/agent/session-token.d.ts.map +1 -0
  21. package/dist/src/agent/session-token.js +15 -0
  22. package/dist/src/agent/session-token.js.map +1 -0
  23. package/dist/src/api/activity-ops.d.ts +2 -0
  24. package/dist/src/api/activity-ops.d.ts.map +1 -0
  25. package/dist/src/api/activity-ops.js +71 -0
  26. package/dist/src/api/activity-ops.js.map +1 -0
  27. package/dist/src/api/base-url.d.ts +3 -0
  28. package/dist/src/api/base-url.d.ts.map +1 -0
  29. package/dist/src/api/base-url.js +11 -0
  30. package/dist/src/api/base-url.js.map +1 -0
  31. package/dist/src/api/delegation-ops.d.ts +2 -0
  32. package/dist/src/api/delegation-ops.d.ts.map +1 -0
  33. package/dist/src/api/delegation-ops.js +51 -0
  34. package/dist/src/api/delegation-ops.js.map +1 -0
  35. package/dist/src/api/issue-ops.d.ts +2 -0
  36. package/dist/src/api/issue-ops.d.ts.map +1 -0
  37. package/dist/src/api/issue-ops.js +170 -0
  38. package/dist/src/api/issue-ops.js.map +1 -0
  39. package/dist/src/api/query-ops.d.ts +2 -0
  40. package/dist/src/api/query-ops.d.ts.map +1 -0
  41. package/dist/src/api/query-ops.js +77 -0
  42. package/dist/src/api/query-ops.js.map +1 -0
  43. package/dist/src/api/router.d.ts +12 -0
  44. package/dist/src/api/router.d.ts.map +1 -0
  45. package/dist/src/api/router.js +62 -0
  46. package/dist/src/api/router.js.map +1 -0
  47. package/dist/src/api/session-ops.d.ts +2 -0
  48. package/dist/src/api/session-ops.d.ts.map +1 -0
  49. package/dist/src/api/session-ops.js +96 -0
  50. package/dist/src/api/session-ops.js.map +1 -0
  51. package/dist/src/config.d.ts +3 -0
  52. package/dist/src/config.d.ts.map +1 -0
  53. package/dist/src/config.js +47 -0
  54. package/dist/src/config.js.map +1 -0
  55. package/dist/src/graphql/mutations.d.ts +9 -0
  56. package/dist/src/graphql/mutations.d.ts.map +1 -0
  57. package/dist/src/graphql/mutations.js +74 -0
  58. package/dist/src/graphql/mutations.js.map +1 -0
  59. package/dist/src/graphql/queries.d.ts +10 -0
  60. package/dist/src/graphql/queries.d.ts.map +1 -0
  61. package/dist/src/graphql/queries.js +121 -0
  62. package/dist/src/graphql/queries.js.map +1 -0
  63. package/dist/src/linear-client.d.ts +7 -0
  64. package/dist/src/linear-client.d.ts.map +1 -0
  65. package/dist/src/linear-client.js +72 -0
  66. package/dist/src/linear-client.js.map +1 -0
  67. package/dist/src/types.d.ts +85 -0
  68. package/dist/src/types.d.ts.map +1 -0
  69. package/dist/src/types.js +2 -0
  70. package/dist/src/types.js.map +1 -0
  71. package/dist/src/util.d.ts +13 -0
  72. package/dist/src/util.d.ts.map +1 -0
  73. package/dist/src/util.js +80 -0
  74. package/dist/src/util.js.map +1 -0
  75. package/dist/src/webhook/close-intent.d.ts +4 -0
  76. package/dist/src/webhook/close-intent.d.ts.map +1 -0
  77. package/dist/src/webhook/close-intent.js +37 -0
  78. package/dist/src/webhook/close-intent.js.map +1 -0
  79. package/dist/src/webhook/handler.d.ts +5 -0
  80. package/dist/src/webhook/handler.d.ts.map +1 -0
  81. package/dist/src/webhook/handler.js +441 -0
  82. package/dist/src/webhook/handler.js.map +1 -0
  83. package/dist/src/webhook/issue-policy.d.ts +7 -0
  84. package/dist/src/webhook/issue-policy.d.ts.map +1 -0
  85. package/dist/src/webhook/issue-policy.js +139 -0
  86. package/dist/src/webhook/issue-policy.js.map +1 -0
  87. package/dist/src/webhook/message-builder.d.ts +34 -0
  88. package/dist/src/webhook/message-builder.d.ts.map +1 -0
  89. package/dist/src/webhook/message-builder.js +144 -0
  90. package/dist/src/webhook/message-builder.js.map +1 -0
  91. package/dist/src/webhook/response-parser.d.ts +2 -0
  92. package/dist/src/webhook/response-parser.d.ts.map +1 -0
  93. package/dist/src/webhook/response-parser.js +51 -0
  94. package/dist/src/webhook/response-parser.js.map +1 -0
  95. package/dist/src/webhook/session-resolver.d.ts +6 -0
  96. package/dist/src/webhook/session-resolver.d.ts.map +1 -0
  97. package/dist/src/webhook/session-resolver.js +203 -0
  98. package/dist/src/webhook/session-resolver.js.map +1 -0
  99. package/dist/src/webhook/skip-filter.d.ts +4 -0
  100. package/dist/src/webhook/skip-filter.d.ts.map +1 -0
  101. package/dist/src/webhook/skip-filter.js +42 -0
  102. package/dist/src/webhook/skip-filter.js.map +1 -0
  103. package/dist/src/webhook/validation.d.ts +2 -0
  104. package/dist/src/webhook/validation.d.ts.map +1 -0
  105. package/dist/src/webhook/validation.js +11 -0
  106. package/dist/src/webhook/validation.js.map +1 -0
  107. package/openclaw.plugin.json +92 -0
  108. package/package.json +51 -0
@@ -0,0 +1,72 @@
1
+ import { readObject, readString } from "./util.js";
2
+ const LINEAR_API_URL = "https://api.linear.app/graphql";
3
+ const warnRef = { value: false };
4
+ const viewerRef = {};
5
+ export async function callLinear(api, cfg, label, body) {
6
+ const token = cfg.linearApiKey;
7
+ if (!token) {
8
+ warnMissingApiKey(api);
9
+ return { ok: false };
10
+ }
11
+ const res = await fetch(LINEAR_API_URL, {
12
+ method: "POST",
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ Authorization: `Bearer ${token}`,
16
+ },
17
+ body: JSON.stringify(body),
18
+ }).catch(() => null);
19
+ if (!res) {
20
+ api.logger.warn?.(`linear ${label} failed: fetch error`);
21
+ return { ok: false };
22
+ }
23
+ if (!res.ok) {
24
+ const detail = await res.text();
25
+ api.logger.warn?.(`linear ${label} failed (${res.status}): ${detail}`);
26
+ return { ok: false };
27
+ }
28
+ const json = await res.json().catch(() => null);
29
+ const root = readObject(json);
30
+ if (!root) {
31
+ api.logger.warn?.(`linear ${label} invalid response`);
32
+ return { ok: false };
33
+ }
34
+ const errors = root.errors;
35
+ if (Array.isArray(errors) && errors.length > 0) {
36
+ const detail = errors
37
+ .map((item) => readString(readObject(item)?.message) ?? "error")
38
+ .filter(Boolean)
39
+ .join("; ");
40
+ api.logger.warn?.(`linear ${label} failed: ${detail}`);
41
+ return { ok: false };
42
+ }
43
+ const data = readObject(root.data);
44
+ if (!data) {
45
+ api.logger.warn?.(`linear ${label} missing data`);
46
+ return { ok: false };
47
+ }
48
+ return { ok: true, data };
49
+ }
50
+ export async function resolveViewer(api, cfg) {
51
+ if (viewerRef.value)
52
+ return viewerRef.value;
53
+ const { VIEWER_QUERY } = await import("./graphql/queries.js");
54
+ const result = await callLinear(api, cfg, "viewer", {
55
+ query: VIEWER_QUERY,
56
+ variables: {},
57
+ });
58
+ if (!result.ok)
59
+ return "";
60
+ const viewer = readObject(result.data.viewer);
61
+ const id = readString(viewer?.id) ?? "";
62
+ if (id)
63
+ viewerRef.value = id;
64
+ return id;
65
+ }
66
+ function warnMissingApiKey(api) {
67
+ if (warnRef.value)
68
+ return;
69
+ warnRef.value = true;
70
+ api.logger.warn?.("linearApiKey missing; AgentActivity updates disabled");
71
+ }
72
+ //# sourceMappingURL=linear-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-client.js","sourceRoot":"","sources":["../../src/linear-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ export interface OpenClawPluginApi {
3
+ pluginConfig?: Record<string, unknown>;
4
+ config?: {
5
+ gateway?: {
6
+ auth?: {
7
+ token?: string;
8
+ password?: string;
9
+ };
10
+ };
11
+ };
12
+ logger: {
13
+ info?: (msg: string) => void;
14
+ warn?: (msg: string) => void;
15
+ error?: (msg: string) => void;
16
+ debug?: (msg: string) => void;
17
+ };
18
+ callGateway?: unknown;
19
+ registerHttpRoute: (opts: {
20
+ path: string;
21
+ handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
22
+ }) => void;
23
+ }
24
+ export interface PluginConfig {
25
+ devAgentId?: string;
26
+ linearWebhookSecret?: string;
27
+ linearApiKey?: string;
28
+ notifyChannel?: string;
29
+ notifyTo?: string;
30
+ notifyAccountId?: string;
31
+ repoByTeam?: Record<string, string>;
32
+ repoByProject?: Record<string, string>;
33
+ defaultDir?: string;
34
+ delegateOnCreate?: boolean;
35
+ startOnCreate?: boolean;
36
+ externalUrlBase?: string;
37
+ externalUrlLabel?: string;
38
+ enableAgentApi?: boolean;
39
+ apiBaseUrl?: string;
40
+ }
41
+ export type ActivityType = "thought" | "elicitation" | "action" | "response" | "error";
42
+ export interface ActivityContent {
43
+ type: ActivityType;
44
+ body?: string;
45
+ action?: string;
46
+ parameter?: string;
47
+ result?: string;
48
+ }
49
+ export interface ActivityOptions {
50
+ signal?: string;
51
+ signalMeta?: Record<string, unknown>;
52
+ ephemeral?: boolean;
53
+ }
54
+ export interface PlanStep {
55
+ content: string;
56
+ status: "pending" | "inProgress" | "completed" | "canceled";
57
+ }
58
+ export interface SessionContext {
59
+ sessionId: string;
60
+ issueId: string;
61
+ issueIdentifier: string;
62
+ issueTitle: string;
63
+ issueUrl: string;
64
+ teamId: string;
65
+ apiToken: string;
66
+ }
67
+ export interface LinearCallResult {
68
+ ok: boolean;
69
+ data?: Record<string, unknown>;
70
+ }
71
+ export type ReadBodyResult = {
72
+ ok: true;
73
+ body: Buffer;
74
+ } | {
75
+ ok: false;
76
+ status: number;
77
+ error: string;
78
+ };
79
+ export interface IssueInfo {
80
+ id: string;
81
+ teamId: string;
82
+ stateType: string;
83
+ delegateId: string;
84
+ }
85
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { ReadBodyResult } from "./types.js";
3
+ export declare function readString(input: unknown): string | undefined;
4
+ export declare function readNumber(input: unknown): number | undefined;
5
+ export declare function readObject(input: unknown): Record<string, unknown> | undefined;
6
+ export declare function readArray(input: unknown): unknown[];
7
+ export declare function sleep(ms: number): Promise<void>;
8
+ export declare function readHeader(req: IncomingMessage, name: string): string | undefined;
9
+ export declare function readBody(req: IncomingMessage, limit: number): Promise<ReadBodyResult>;
10
+ export declare function sendJson(res: ServerResponse, status: number, data: unknown): void;
11
+ export declare function normalizeKey(input: string): string;
12
+ export declare function resolveFlag(value: unknown, fallback: boolean): boolean;
13
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI7D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG7D;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAIrC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,CAEnD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA6BrF;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,IAAI,CAIN;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,OAAO,GAChB,OAAO,CAET"}
@@ -0,0 +1,80 @@
1
+ export function readString(input) {
2
+ if (typeof input !== "string")
3
+ return undefined;
4
+ const value = input.trim();
5
+ return value || undefined;
6
+ }
7
+ export function readNumber(input) {
8
+ if (typeof input !== "number" || Number.isNaN(input))
9
+ return undefined;
10
+ return input;
11
+ }
12
+ export function readObject(input) {
13
+ if (!input || typeof input !== "object" || Array.isArray(input))
14
+ return undefined;
15
+ return input;
16
+ }
17
+ export function readArray(input) {
18
+ return Array.isArray(input) ? input : [];
19
+ }
20
+ export function sleep(ms) {
21
+ return new Promise((resolve) => {
22
+ setTimeout(resolve, ms);
23
+ });
24
+ }
25
+ export function readHeader(req, name) {
26
+ const value = req.headers[name];
27
+ if (Array.isArray(value))
28
+ return value[0];
29
+ return typeof value === "string" ? value : undefined;
30
+ }
31
+ export function readBody(req, limit) {
32
+ return new Promise((resolve) => {
33
+ const chunks = [];
34
+ let size = 0;
35
+ let done = false;
36
+ const finish = (value) => {
37
+ if (done)
38
+ return;
39
+ done = true;
40
+ resolve(value);
41
+ };
42
+ req.on("data", (chunk) => {
43
+ const buf = Buffer.isBuffer(chunk)
44
+ ? chunk
45
+ : Buffer.from(String(chunk));
46
+ size += buf.length;
47
+ if (size > limit) {
48
+ req.destroy();
49
+ finish({ ok: false, status: 413, error: "payload too large" });
50
+ return;
51
+ }
52
+ chunks.push(buf);
53
+ });
54
+ req.on("end", () => {
55
+ finish({ ok: true, body: Buffer.concat(chunks) });
56
+ });
57
+ req.on("error", () => {
58
+ finish({ ok: false, status: 400, error: "read error" });
59
+ });
60
+ });
61
+ }
62
+ export function sendJson(res, status, data) {
63
+ res.statusCode = status;
64
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
65
+ res.end(JSON.stringify(data));
66
+ }
67
+ export function normalizeKey(input) {
68
+ const lower = input.trim().toLowerCase();
69
+ if (!lower)
70
+ return "issue";
71
+ return (lower
72
+ .replace(/[^a-z0-9_-]+/g, "-")
73
+ .replace(/^-+/, "")
74
+ .replace(/-+$/, "")
75
+ .slice(0, 64) || "issue");
76
+ }
77
+ export function resolveFlag(value, fallback) {
78
+ return typeof value === "boolean" ? value : fallback;
79
+ }
80
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { OpenClawPluginApi, PluginConfig } from "../types.js";
2
+ export declare function isCloseIntentPrompt(prompt: string): boolean;
3
+ export declare function closeIssueFromPrompt(api: OpenClawPluginApi, cfg: PluginConfig, issueId: string, id: string, title: string): Promise<string>;
4
+ //# sourceMappingURL=close-intent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-intent.d.ts","sourceRoot":"","sources":["../../../src/webhook/close-intent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAgB3D;AAED,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
@@ -0,0 +1,37 @@
1
+ import { resolveIssueInfo, resolveCompletedState, updateIssue } from "./issue-policy.js";
2
+ export function isCloseIntentPrompt(prompt) {
3
+ const text = (prompt ?? "").trim().toLowerCase();
4
+ if (!text)
5
+ return false;
6
+ if (/(не\s+закры(вай|ть|вайте|й)?)/.test(text) ||
7
+ /(don't\s+close|do\s+not\s+close)/.test(text))
8
+ return false;
9
+ if (/(закрой|закрыть|закройте|закрывай)/.test(text))
10
+ return true;
11
+ if (/\bclose\b/.test(text) &&
12
+ /\b(task|issue|ticket|таск|задач[ауые]?)\b/.test(text))
13
+ return true;
14
+ if (/\bmark\b.*\bdone\b/.test(text))
15
+ return true;
16
+ return false;
17
+ }
18
+ export async function closeIssueFromPrompt(api, cfg, issueId, id, title) {
19
+ const label = id || title || "задача";
20
+ const info = await resolveIssueInfo(api, cfg, issueId);
21
+ if (!info)
22
+ return `Не удалось получить данные задачи ${label}.`;
23
+ if (info.stateType === "completed")
24
+ return `${label} уже закрыта (completed).`;
25
+ if (info.stateType === "canceled")
26
+ return `${label} уже в статусе canceled.`;
27
+ if (!info.teamId)
28
+ return `Не удалось определить workflow команды для ${label}.`;
29
+ const stateId = await resolveCompletedState(api, cfg, info.teamId);
30
+ if (!stateId)
31
+ return `Не удалось найти статус completed для ${label}.`;
32
+ const ok = await updateIssue(api, cfg, info.id, { stateId }, "issueUpdate(close)");
33
+ if (!ok)
34
+ return `Не удалось закрыть ${label}. Проверьте права Linear API.`;
35
+ return `Готово: закрыл ${label}.`;
36
+ }
37
+ //# sourceMappingURL=close-intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-intent.js","sourceRoot":"","sources":["../../../src/webhook/close-intent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzF,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,IACE,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1C,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC;QAE7C,OAAO,KAAK,CAAC;IACf,IAAI,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,IACE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QACtB,2CAA2C,CAAC,IAAI,CAAC,IAAI,CAAC;QAEtD,OAAO,IAAI,CAAC;IACd,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAsB,EACtB,GAAiB,EACjB,OAAe,EACf,EAAU,EACV,KAAa;IAEb,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,IAAI,QAAQ,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI;QAAE,OAAO,qCAAqC,KAAK,GAAG,CAAC;IAChE,IAAI,IAAI,CAAC,SAAS,KAAK,WAAW;QAChC,OAAO,GAAG,KAAK,2BAA2B,CAAC;IAC7C,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU;QAC/B,OAAO,GAAG,KAAK,0BAA0B,CAAC;IAC5C,IAAI,CAAC,IAAI,CAAC,MAAM;QACd,OAAO,8CAA8C,KAAK,GAAG,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC,OAAO;QAAE,OAAO,yCAAyC,KAAK,GAAG,CAAC;IACvE,MAAM,EAAE,GAAG,MAAM,WAAW,CAC1B,GAAG,EACH,GAAG,EACH,IAAI,CAAC,EAAE,EACP,EAAE,OAAO,EAAE,EACX,oBAAoB,CACrB,CAAC;IACF,IAAI,CAAC,EAAE;QAAE,OAAO,sBAAsB,KAAK,+BAA+B,CAAC;IAC3E,OAAO,kBAAkB,KAAK,GAAG,CAAC;AACpC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { OpenClawPluginApi, PluginConfig, ActivityContent, ActivityOptions } from "../types.js";
3
+ export declare function createLinearWebhook(api: OpenClawPluginApi): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
4
+ export declare function postActivity(api: OpenClawPluginApi, cfg: PluginConfig, session: string, content: ActivityContent, opts?: ActivityOptions): Promise<void>;
5
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/webhook/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAKjE,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,eAAe,EAChB,MAAM,aAAa,CAAC;AAsDrB,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,iBAAiB,GACrB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CA0D9D;AA0PD,wBAAsB,YAAY,CAChC,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,EACxB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAiBf"}