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 @@
1
+ {"version":3,"file":"message-builder.d.ts","sourceRoot":"","sources":["../../../src/webhook/message-builder.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiC1D;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,MAAM,CAOR;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,wBAAgB,WAAW,CACzB,GAAG,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EACzG,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,CAIR;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAkBnE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAcnE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAInE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIjD;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKvC"}
@@ -0,0 +1,144 @@
1
+ import { readObject, readString } from "../util.js";
2
+ export function buildLabel(id, title) {
3
+ if (id && title)
4
+ return `Linear ${id} ${title}`.slice(0, 80);
5
+ if (id)
6
+ return `Linear ${id}`;
7
+ if (title)
8
+ return `Linear ${title}`.slice(0, 80);
9
+ return "Linear issue";
10
+ }
11
+ export function buildMessage(params) {
12
+ const issueLine = params.id || params.title
13
+ ? `Linear issue: ${params.id} ${params.title}`.trim()
14
+ : "";
15
+ const actionLine = params.action
16
+ ? `Linear action: ${params.action}`
17
+ : "";
18
+ const guidanceLine = params.context
19
+ ? ""
20
+ : params.guidance
21
+ ? `Guidance:\n${params.guidance}`
22
+ : "";
23
+ const descLine = params.context
24
+ ? ""
25
+ : params.desc
26
+ ? `Description:\n${params.desc}`
27
+ : "";
28
+ const contextLine = params.context
29
+ ? `Prompt context:\n${params.context}`
30
+ : "";
31
+ const lines = [
32
+ actionLine,
33
+ issueLine,
34
+ params.url ? `URL: ${params.url}` : "",
35
+ params.repo ? `Repo: ${params.repo}` : "",
36
+ params.session ? `Agent session: ${params.session}` : "",
37
+ contextLine,
38
+ params.prompt ? `User prompt:\n${params.prompt}` : "",
39
+ guidanceLine,
40
+ descLine,
41
+ ];
42
+ return lines.filter(Boolean).join("\n\n");
43
+ }
44
+ export function buildThought(action, id, title) {
45
+ const target = id || title ? `${id} ${title}`.trim() : "Linear issue";
46
+ if (action === "prompted") {
47
+ return `Received an update on ${target}. Continuing work.`;
48
+ }
49
+ return `Starting work on ${target}.`;
50
+ }
51
+ export function buildStopText(id, title) {
52
+ const target = id || title ? `${id} ${title}`.trim() : "this request";
53
+ return `Stop request received. I will halt work on ${target}.`;
54
+ }
55
+ export function resolveRepo(cfg, team, proj) {
56
+ if (proj && cfg.repoByProject?.[proj])
57
+ return cfg.repoByProject[proj];
58
+ if (team && cfg.repoByTeam?.[team])
59
+ return cfg.repoByTeam[team];
60
+ return cfg.defaultDir ?? "";
61
+ }
62
+ export function resolveAction(data) {
63
+ const kind = readString(data.type) ?? "";
64
+ const rawAction = (readString(data.action) ?? "")
65
+ .trim()
66
+ .toLowerCase();
67
+ if (kind === "Comment") {
68
+ if (rawAction &&
69
+ rawAction !== "create" &&
70
+ rawAction !== "created" &&
71
+ rawAction !== "prompted")
72
+ return "";
73
+ return "prompted";
74
+ }
75
+ if (rawAction === "create" || rawAction === "created")
76
+ return "created";
77
+ if (rawAction === "prompt" || rawAction === "prompted")
78
+ return "prompted";
79
+ return "";
80
+ }
81
+ export function resolvePrompt(data) {
82
+ const activity = readObject(data.agentActivity);
83
+ const direct = readString(activity?.body);
84
+ if (direct)
85
+ return direct;
86
+ const content = readObject(activity?.content);
87
+ const body = readString(content?.body);
88
+ if (body)
89
+ return body;
90
+ const comment = readObject(data.comment);
91
+ return (readString(comment?.body) ??
92
+ readString(data.body) ??
93
+ readString(data.message) ??
94
+ "");
95
+ }
96
+ export function resolveSignal(data) {
97
+ const activity = readObject(data.agentActivity);
98
+ const signal = readString(activity?.signal);
99
+ return signal || readString(data.signal) || "";
100
+ }
101
+ export function resolveContext(data) {
102
+ return readString(data.promptContext) ?? "";
103
+ }
104
+ export function resolveKey(input) {
105
+ const obj = readObject(input);
106
+ if (!obj)
107
+ return "";
108
+ return readString(obj.key) ?? readString(obj.id) ?? readString(obj.name) ?? "";
109
+ }
110
+ export function resolveExternal(cfg, session, issueId) {
111
+ const base = cfg.externalUrlBase ?? "";
112
+ const label = cfg.externalUrlLabel ?? "OpenClaw session";
113
+ const url = buildExternalUrl(base, session, issueId);
114
+ return url ? { url, label } : null;
115
+ }
116
+ function buildExternalUrl(base, session, issueId) {
117
+ const raw = base.trim();
118
+ if (!raw)
119
+ return "";
120
+ const sessionToken = session ?? "";
121
+ const issueToken = issueId ?? "";
122
+ const needsSession = raw.includes("{session}") || raw.includes("${session}");
123
+ const needsIssue = raw.includes("{issue}") || raw.includes("${issue}");
124
+ if (needsSession && !sessionToken)
125
+ return "";
126
+ if (needsIssue && !issueToken)
127
+ return "";
128
+ if (needsSession || needsIssue) {
129
+ return raw
130
+ .replaceAll("{session}", sessionToken)
131
+ .replaceAll("${session}", sessionToken)
132
+ .replaceAll("{issue}", issueToken)
133
+ .replaceAll("${issue}", issueToken);
134
+ }
135
+ if (!URL.canParse(raw))
136
+ return "";
137
+ const url = new URL(raw);
138
+ if (sessionToken)
139
+ url.searchParams.set("session", sessionToken);
140
+ if (issueToken)
141
+ url.searchParams.set("issue", issueToken);
142
+ return url.toString();
143
+ }
144
+ //# sourceMappingURL=message-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-builder.js","sourceRoot":"","sources":["../../../src/webhook/message-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function buildAgentResponse(input: unknown): string;
2
+ //# sourceMappingURL=response-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-parser.d.ts","sourceRoot":"","sources":["../../../src/webhook/response-parser.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUzD"}
@@ -0,0 +1,51 @@
1
+ import { readArray, readObject, readString } from "../util.js";
2
+ export function buildAgentResponse(input) {
3
+ const payload = readObject(input);
4
+ if (!payload)
5
+ return "";
6
+ const result = readObject(payload.result);
7
+ const payloads = readArray(result?.payloads);
8
+ const text = collectPayloadText(payloads);
9
+ if (text)
10
+ return text;
11
+ const status = readString(payload.status) ?? "";
12
+ if (status === "ok")
13
+ return "Agent completed with no reply.";
14
+ return "";
15
+ }
16
+ function collectPayloadText(payloads) {
17
+ if (payloads.length === 0)
18
+ return "";
19
+ const lines = [];
20
+ const seenMedia = new Set();
21
+ for (const entry of payloads) {
22
+ const item = readObject(entry);
23
+ if (!item)
24
+ continue;
25
+ const text = readString(item.text);
26
+ if (text)
27
+ lines.push(text);
28
+ const media = collectMediaUrls(item, seenMedia);
29
+ for (const url of media)
30
+ lines.push(`Media: ${url}`);
31
+ }
32
+ return lines.join("\n\n");
33
+ }
34
+ function collectMediaUrls(item, seen) {
35
+ const urls = [];
36
+ const direct = readString(item.mediaUrl);
37
+ if (direct && !seen.has(direct)) {
38
+ seen.add(direct);
39
+ urls.push(direct);
40
+ }
41
+ const list = readArray(item.mediaUrls);
42
+ for (const entry of list) {
43
+ const url = readString(entry);
44
+ if (url && !seen.has(url)) {
45
+ seen.add(url);
46
+ urls.push(url);
47
+ }
48
+ }
49
+ return urls;
50
+ }
51
+ //# sourceMappingURL=response-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-parser.js","sourceRoot":"","sources":["../../../src/webhook/response-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,gCAAgC,CAAC;IAC7D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAmB;IAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAChD,KAAK,MAAM,GAAG,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,gBAAgB,CACvB,IAA6B,EAC7B,IAAiB;IAEjB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { OpenClawPluginApi, PluginConfig } from "../types.js";
2
+ export declare function resolveSessionId(data: Record<string, unknown>): string;
3
+ export declare function rememberSessionHint(data: Record<string, unknown>, sessionId: string): void;
4
+ export declare function resolveSessionIdWithFallback(api: OpenClawPluginApi, cfg: PluginConfig, data: Record<string, unknown>): Promise<string>;
5
+ export declare function resolveIssue(data: Record<string, unknown>): Record<string, unknown> | undefined;
6
+ //# sourceMappingURL=session-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.d.ts","sourceRoot":"","sources":["../../../src/webhook/session-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWnE,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAoBR;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,GAChB,IAAI,CAeN;AAED,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAoDjB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAmBrC"}
@@ -0,0 +1,203 @@
1
+ import { callLinear } from "../linear-client.js";
2
+ import { COMMENT_SESSION_QUERY, ISSUE_SESSION_QUERY, } from "../graphql/queries.js";
3
+ import { readArray, readObject, readString, sleep } from "../util.js";
4
+ const sessionByIssueRef = {};
5
+ const sessionByCommentRef = {};
6
+ export function resolveSessionId(data) {
7
+ const direct = readString(data.agentSession);
8
+ if (direct)
9
+ return direct;
10
+ const directId = readString(data.agentSessionId);
11
+ if (directId)
12
+ return directId;
13
+ const session = readObject(data.agentSession);
14
+ const sessionId = readString(session?.id) ?? readString(session?.agentSessionId);
15
+ if (sessionId)
16
+ return sessionId;
17
+ const activity = readObject(data.agentActivity);
18
+ const activityId = readString(activity?.agentSessionId);
19
+ if (activityId)
20
+ return activityId;
21
+ const activitySession = readObject(activity?.agentSession);
22
+ const activitySessionId = readString(activitySession?.id);
23
+ if (activitySessionId)
24
+ return activitySessionId;
25
+ const comment = readObject(data.comment);
26
+ const commentId = readString(comment?.agentSessionId);
27
+ if (commentId)
28
+ return commentId;
29
+ const commentSession = readObject(comment?.agentSession);
30
+ return readString(commentSession?.id) ?? "";
31
+ }
32
+ export function rememberSessionHint(data, sessionId) {
33
+ if (!sessionId)
34
+ return;
35
+ const issue = resolveIssue(data);
36
+ const issueId = readString(issue?.id) ?? readString(data.issueId) ?? "";
37
+ if (issueId)
38
+ sessionByIssueRef[issueId] = sessionId;
39
+ const comment = readObject(data.comment);
40
+ const cid = readString(comment?.id) ?? readString(data.id) ?? "";
41
+ if (cid)
42
+ sessionByCommentRef[cid] = sessionId;
43
+ const parentId = readString(comment?.parentId) ??
44
+ readString(data.parentId) ??
45
+ "";
46
+ if (parentId)
47
+ sessionByCommentRef[parentId] = sessionId;
48
+ }
49
+ export async function resolveSessionIdWithFallback(api, cfg, data) {
50
+ const direct = resolveSessionId(data);
51
+ if (direct) {
52
+ rememberSessionHint(data, direct);
53
+ return direct;
54
+ }
55
+ const kind = readString(data.type) ?? "";
56
+ if (kind !== "Comment")
57
+ return "";
58
+ const comment = readObject(data.comment);
59
+ const issueId = readString(resolveIssue(data)?.id) ??
60
+ readString(data.issueId) ??
61
+ readString(comment?.issueId) ??
62
+ "";
63
+ if (issueId && sessionByIssueRef[issueId]) {
64
+ return sessionByIssueRef[issueId];
65
+ }
66
+ const commentId = readString(comment?.id) ?? readString(data.id) ?? "";
67
+ if (commentId && sessionByCommentRef[commentId]) {
68
+ return sessionByCommentRef[commentId];
69
+ }
70
+ const parentId = readString(comment?.parentId) ??
71
+ readString(data.parentId) ??
72
+ "";
73
+ if (parentId && sessionByCommentRef[parentId]) {
74
+ return sessionByCommentRef[parentId];
75
+ }
76
+ const viaParent = await resolveSessionFromCommentWithRetry(api, cfg, parentId);
77
+ if (viaParent) {
78
+ rememberSessionHint({ ...data, id: parentId }, viaParent);
79
+ return viaParent;
80
+ }
81
+ const viaComment = await resolveSessionFromCommentWithRetry(api, cfg, commentId);
82
+ if (viaComment) {
83
+ rememberSessionHint({ ...data, parentId }, viaComment);
84
+ return viaComment;
85
+ }
86
+ if (!issueId)
87
+ return "";
88
+ const viaIssue = await resolveSessionFromIssue(api, cfg, issueId);
89
+ if (viaIssue)
90
+ rememberSessionHint(data, viaIssue);
91
+ return viaIssue;
92
+ }
93
+ export function resolveIssue(data) {
94
+ const issue = readObject(data.issue);
95
+ if (issue)
96
+ return issue;
97
+ const issueId = readString(data.issueId);
98
+ if (issueId)
99
+ return { id: issueId };
100
+ const comment = readObject(data.comment);
101
+ const commentIssue = readObject(comment?.issue);
102
+ if (commentIssue)
103
+ return commentIssue;
104
+ const commentIssueId = readString(comment?.issueId);
105
+ if (commentIssueId)
106
+ return { id: commentIssueId };
107
+ const session = readObject(data.agentSession);
108
+ const sessionIssue = session ? readObject(session.issue) : undefined;
109
+ if (sessionIssue)
110
+ return sessionIssue;
111
+ const activity = readObject(data.agentActivity);
112
+ const activityIssue = readObject(activity?.issue);
113
+ if (activityIssue)
114
+ return activityIssue;
115
+ const activityIssueId = readString(activity?.issueId);
116
+ if (activityIssueId)
117
+ return { id: activityIssueId };
118
+ return undefined;
119
+ }
120
+ async function resolveSessionFromCommentWithRetry(api, cfg, commentId) {
121
+ if (!commentId)
122
+ return "";
123
+ const delays = [120, 350, 800];
124
+ for (let i = 0; i < delays.length; i += 1) {
125
+ const id = await resolveSessionFromComment(api, cfg, commentId);
126
+ if (id)
127
+ return id;
128
+ if (i < delays.length - 1)
129
+ await sleep(delays[i]);
130
+ }
131
+ return "";
132
+ }
133
+ async function resolveSessionFromComment(api, cfg, commentId) {
134
+ if (!commentId)
135
+ return "";
136
+ const result = await callLinear(api, cfg, "comment(agentSession)", {
137
+ query: COMMENT_SESSION_QUERY,
138
+ variables: { id: commentId },
139
+ });
140
+ if (!result.ok)
141
+ return "";
142
+ const comment = readObject(result.data.comment);
143
+ if (!comment)
144
+ return "";
145
+ return pickSessionIdFromComment(comment);
146
+ }
147
+ function pickSessionIdFromComment(comment) {
148
+ const session = readObject(comment.agentSession);
149
+ const direct = readString(session?.id);
150
+ if (direct)
151
+ return direct;
152
+ const list = readArray(readObject(comment.agentSessions)?.nodes);
153
+ for (const entry of list) {
154
+ const id = readString(readObject(entry)?.id);
155
+ if (id)
156
+ return id;
157
+ }
158
+ const parent = readObject(comment.parent);
159
+ if (!parent)
160
+ return "";
161
+ const parentSession = readObject(parent.agentSession);
162
+ const parentDirect = readString(parentSession?.id);
163
+ if (parentDirect)
164
+ return parentDirect;
165
+ const parentList = readArray(readObject(parent.agentSessions)?.nodes);
166
+ for (const entry of parentList) {
167
+ const id = readString(readObject(entry)?.id);
168
+ if (id)
169
+ return id;
170
+ }
171
+ return "";
172
+ }
173
+ async function resolveSessionFromIssue(api, cfg, issueId) {
174
+ if (!issueId)
175
+ return "";
176
+ const result = await callLinear(api, cfg, "issue(session)", {
177
+ query: ISSUE_SESSION_QUERY,
178
+ variables: { id: issueId },
179
+ });
180
+ if (!result.ok)
181
+ return "";
182
+ const issue = readObject(result.data.issue);
183
+ const comments = readObject(issue?.comments);
184
+ const nodes = readArray(comments?.nodes);
185
+ for (const node of nodes) {
186
+ const comment = readObject(node);
187
+ if (!comment)
188
+ continue;
189
+ const sid = pickSessionIdFromComment(comment);
190
+ if (!sid)
191
+ continue;
192
+ const cid = readString(comment.id);
193
+ const pid = readString(comment.parentId);
194
+ sessionByIssueRef[issueId] = sid;
195
+ if (cid)
196
+ sessionByCommentRef[cid] = sid;
197
+ if (pid)
198
+ sessionByCommentRef[pid] = sid;
199
+ return sid;
200
+ }
201
+ return "";
202
+ }
203
+ //# sourceMappingURL=session-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.js","sourceRoot":"","sources":["../../../src/webhook/session-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { OpenClawPluginApi, PluginConfig } from "../types.js";
2
+ export declare function shouldSkipPromptedRun(prompt: string): string;
3
+ export declare function isSelfAuthoredComment(api: OpenClawPluginApi, cfg: PluginConfig, data: Record<string, unknown>): Promise<boolean>;
4
+ //# sourceMappingURL=skip-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skip-filter.d.ts","sourceRoot":"","sources":["../../../src/webhook/skip-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAInE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAa5D;AAED,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,OAAO,CAAC,CAKlB"}
@@ -0,0 +1,42 @@
1
+ import { resolveViewer } from "../linear-client.js";
2
+ import { readObject, readString } from "../util.js";
3
+ export function shouldSkipPromptedRun(prompt) {
4
+ const text = (prompt ?? "").trim();
5
+ if (!text)
6
+ return "empty-prompt";
7
+ const lower = text.toLowerCase();
8
+ const systemEcho = [
9
+ /^received an update on\b/,
10
+ /^starting work on\b/,
11
+ /^stop request received\b/,
12
+ /^agent run failed:/,
13
+ /^working\s+\d{1,2}:\d{2}\b/,
14
+ /^thinking\s+\d{1,2}:\d{2}\b/,
15
+ ].some((re) => re.test(lower));
16
+ return systemEcho ? "system-echo" : "";
17
+ }
18
+ export async function isSelfAuthoredComment(api, cfg, data) {
19
+ const authorId = resolveAuthorId(data);
20
+ if (!authorId)
21
+ return false;
22
+ const viewerId = await resolveViewer(api, cfg);
23
+ return Boolean(viewerId && authorId === viewerId);
24
+ }
25
+ function resolveAuthorId(data) {
26
+ const user = readObject(data.user);
27
+ const userId = readString(user?.id);
28
+ if (userId)
29
+ return userId;
30
+ const actor = readObject(data.actor);
31
+ const actorId = readString(actor?.id);
32
+ if (actorId)
33
+ return actorId;
34
+ const comment = readObject(data.comment);
35
+ const commentUser = readObject(comment?.user);
36
+ const commentUserId = readString(commentUser?.id);
37
+ if (commentUserId)
38
+ return commentUserId;
39
+ const commentActor = readObject(comment?.actor);
40
+ return readString(commentActor?.id) ?? "";
41
+ }
42
+ //# sourceMappingURL=skip-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skip-filter.js","sourceRoot":"","sources":["../../../src/webhook/skip-filter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,IAAI;QAAE,OAAO,cAAc,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG;QACjB,0BAA0B;QAC1B,qBAAqB;QACrB,0BAA0B;QAC1B,oBAAoB;QACpB,4BAA4B;QAC5B,6BAA6B;KAC9B,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,OAAO,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAsB,EACtB,GAAiB,EACjB,IAA6B;IAE7B,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,eAAe,CAAC,IAA6B;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAClD,IAAI,aAAa;QAAE,OAAO,aAAa,CAAC;IACxC,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,UAAU,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function verifySignature(secret: string, signature: string | undefined, raw: Buffer): boolean;
2
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/webhook/validation.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,GAAG,EAAE,MAAM,GACV,OAAO,CAMT"}
@@ -0,0 +1,11 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ export function verifySignature(secret, signature, raw) {
3
+ if (!signature)
4
+ return false;
5
+ const header = Buffer.from(signature, "hex");
6
+ const digest = createHmac("sha256", secret).update(raw).digest();
7
+ if (header.length !== digest.length)
8
+ return false;
9
+ return timingSafeEqual(digest, header);
10
+ }
11
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/webhook/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,SAA6B,EAC7B,GAAW;IAEX,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,92 @@
1
+ {
2
+ "id": "linear-agent-bridge",
3
+ "name": "Linear",
4
+ "description": "Linear agent webhook bridge for OpenClaw dev runs",
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "devAgentId": {
10
+ "type": "string",
11
+ "description": "Agent ID to handle Linear issues (default: 'dev')"
12
+ },
13
+ "linearWebhookSecret": {
14
+ "type": "string",
15
+ "description": "Linear webhook signing secret for signature verification"
16
+ },
17
+ "linearApiKey": {
18
+ "type": "string",
19
+ "description": "Linear OAuth token for posting activities and updating issues"
20
+ },
21
+ "notifyChannel": {
22
+ "type": "string",
23
+ "description": "Optional channel to deliver agent responses (e.g., 'discord')"
24
+ },
25
+ "notifyTo": {
26
+ "type": "string",
27
+ "description": "Optional target for notifications (e.g., 'channel:123456')"
28
+ },
29
+ "notifyAccountId": {
30
+ "type": "string",
31
+ "description": "Optional account ID for notifications"
32
+ },
33
+ "repoByTeam": {
34
+ "type": "object",
35
+ "additionalProperties": { "type": "string" },
36
+ "description": "Map Linear team keys to repository directories"
37
+ },
38
+ "repoByProject": {
39
+ "type": "object",
40
+ "additionalProperties": { "type": "string" },
41
+ "description": "Map Linear project keys to repository directories"
42
+ },
43
+ "defaultDir": {
44
+ "type": "string",
45
+ "description": "Default repository directory when no team/project mapping matches"
46
+ },
47
+ "delegateOnCreate": {
48
+ "type": "boolean",
49
+ "description": "Auto-delegate issues to the app user on session create (default: true)"
50
+ },
51
+ "startOnCreate": {
52
+ "type": "boolean",
53
+ "description": "Move issues to 'started' state on session create (default: true)"
54
+ },
55
+ "externalUrlBase": {
56
+ "type": "string",
57
+ "description": "Base URL for external session links (supports {session} and {issue} placeholders)"
58
+ },
59
+ "externalUrlLabel": {
60
+ "type": "string",
61
+ "description": "Label for external session links (default: 'OpenClaw session')"
62
+ },
63
+ "enableAgentApi": {
64
+ "type": "boolean",
65
+ "description": "Enable agent-callable API proxy endpoints (default: true)"
66
+ },
67
+ "apiBaseUrl": {
68
+ "type": "string",
69
+ "description": "Override auto-detected base URL for agent API calls"
70
+ }
71
+ }
72
+ },
73
+ "uiHints": {
74
+ "linearWebhookSecret": { "label": "Webhook secret", "sensitive": true },
75
+ "linearApiKey": { "label": "API key / OAuth token", "sensitive": true },
76
+ "delegateOnCreate": { "label": "Auto delegate" },
77
+ "startOnCreate": { "label": "Move to started" },
78
+ "externalUrlBase": {
79
+ "label": "External session URL",
80
+ "placeholder": "https://your-gateway/sessions/{session}"
81
+ },
82
+ "externalUrlLabel": {
83
+ "label": "External URL label",
84
+ "placeholder": "OpenClaw session"
85
+ },
86
+ "enableAgentApi": { "label": "Enable agent API" },
87
+ "apiBaseUrl": {
88
+ "label": "API base URL override",
89
+ "placeholder": "https://your-hostname.ts.net"
90
+ }
91
+ }
92
+ }