@agentworkforce/sage 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.env.example +5 -4
  2. package/dist/app.d.ts +0 -6
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +264 -217
  5. package/dist/integrations/cloud-proxy-provider.d.ts +42 -0
  6. package/dist/integrations/cloud-proxy-provider.d.ts.map +1 -0
  7. package/dist/integrations/cloud-proxy-provider.js +131 -0
  8. package/dist/integrations/github-context.d.ts +2 -1
  9. package/dist/integrations/github-context.d.ts.map +1 -1
  10. package/dist/integrations/github-context.js +4 -2
  11. package/dist/integrations/github.d.ts +4 -2
  12. package/dist/integrations/github.d.ts.map +1 -1
  13. package/dist/integrations/github.js +16 -11
  14. package/dist/integrations/slack-egress.d.ts +28 -0
  15. package/dist/integrations/slack-egress.d.ts.map +1 -0
  16. package/dist/integrations/slack-egress.js +181 -0
  17. package/dist/integrations/slack-ingress.d.ts +26 -0
  18. package/dist/integrations/slack-ingress.d.ts.map +1 -0
  19. package/dist/integrations/slack-ingress.js +31 -0
  20. package/dist/nango.d.ts +1 -6
  21. package/dist/nango.d.ts.map +1 -1
  22. package/dist/nango.js +9 -34
  23. package/dist/proactive/context-watcher.d.ts +2 -2
  24. package/dist/proactive/context-watcher.d.ts.map +1 -1
  25. package/dist/proactive/context-watcher.js +5 -3
  26. package/dist/proactive/engine.d.ts +5 -9
  27. package/dist/proactive/engine.d.ts.map +1 -1
  28. package/dist/proactive/engine.js +25 -20
  29. package/dist/proactive/evidence-sources/affirmative-reply-source.d.ts.map +1 -1
  30. package/dist/proactive/evidence-sources/affirmative-reply-source.js +4 -2
  31. package/dist/proactive/evidence-sources/explicit-close-source.d.ts.map +1 -1
  32. package/dist/proactive/evidence-sources/explicit-close-source.js +4 -2
  33. package/dist/proactive/evidence-sources/pr-merge-source.d.ts.map +1 -1
  34. package/dist/proactive/evidence-sources/pr-merge-source.js +12 -5
  35. package/dist/proactive/evidence-sources/reaction-source.d.ts.map +1 -1
  36. package/dist/proactive/evidence-sources/reaction-source.js +6 -15
  37. package/dist/proactive/follow-up-checker.d.ts +4 -4
  38. package/dist/proactive/follow-up-checker.d.ts.map +1 -1
  39. package/dist/proactive/follow-up-checker.js +40 -21
  40. package/dist/proactive/integrations/slack-egress.d.ts +2 -0
  41. package/dist/proactive/integrations/slack-egress.d.ts.map +1 -0
  42. package/dist/proactive/integrations/slack-egress.js +1 -0
  43. package/dist/proactive/pr-matcher.d.ts +2 -2
  44. package/dist/proactive/pr-matcher.d.ts.map +1 -1
  45. package/dist/proactive/pr-matcher.js +8 -6
  46. package/dist/proactive/stale-thread-detector.d.ts +2 -2
  47. package/dist/proactive/stale-thread-detector.d.ts.map +1 -1
  48. package/dist/proactive/stale-thread-detector.js +16 -23
  49. package/dist/proactive/types.d.ts +8 -6
  50. package/dist/proactive/types.d.ts.map +1 -1
  51. package/dist/slack.d.ts +3 -13
  52. package/dist/slack.d.ts.map +1 -1
  53. package/dist/slack.js +7 -108
  54. package/dist/types.d.ts +1 -2
  55. package/dist/types.d.ts.map +1 -1
  56. package/package.json +3 -1
package/dist/nango.js CHANGED
@@ -1,12 +1,4 @@
1
1
  import { Nango } from '@nangohq/node';
2
- // Nango provider_config_key values. Only listed here when sage has no other
3
- // way to discover the value at runtime — Slack keys are always sourced from
4
- // the webhook envelope or the cloud workspace-connections resolver, never
5
- // hardcoded, because different deployments register the Slack bot under
6
- // different names (`slack-sage`, `slack-my-senior-dev`, etc).
7
- export const NANGO_INTEGRATIONS = {
8
- GITHUB: 'github-app-oauth',
9
- };
10
2
  const GITHUB_DISCOVERY_TTL_MS = 30 * 60_000;
11
3
  export class NangoError extends Error {
12
4
  operation;
@@ -23,7 +15,6 @@ export class NangoError extends Error {
23
15
  export class NangoClient {
24
16
  client = null;
25
17
  githubOrgDiscoveryCache = new Map();
26
- slackBotUserIdCache = new Map();
27
18
  secretKey;
28
19
  constructor({ secretKey }) {
29
20
  this.secretKey = secretKey;
@@ -47,14 +38,16 @@ export class NangoClient {
47
38
  throw new NangoError('getConnection', connectionId, error);
48
39
  }
49
40
  }
50
- async discoverGitHubOrgs(connectionId) {
51
- const cached = this.githubOrgDiscoveryCache.get(connectionId);
41
+ async discoverGitHubOrgs(connectionId, providerConfigKey) {
42
+ const resolvedProviderConfigKey = providerConfigKey.trim();
43
+ const cacheKey = `${connectionId}:${resolvedProviderConfigKey}`;
44
+ const cached = this.githubOrgDiscoveryCache.get(cacheKey);
52
45
  if (cached && cached.expiresAt > Date.now()) {
53
46
  return cloneGitHubOrgDiscovery(cached.value);
54
47
  }
55
48
  const response = await this.proxy({
56
49
  connectionId,
57
- providerConfigKey: NANGO_INTEGRATIONS.GITHUB,
50
+ providerConfigKey: resolvedProviderConfigKey,
58
51
  method: 'GET',
59
52
  endpoint: '/user/installations',
60
53
  });
@@ -66,7 +59,7 @@ export class NangoClient {
66
59
  continue;
67
60
  }
68
61
  orgs.add(org);
69
- const repoNames = await this.listGitHubInstallationRepos(connectionId, installation);
62
+ const repoNames = await this.listGitHubInstallationRepos(connectionId, resolvedProviderConfigKey, installation);
70
63
  if (!reposByOrg.has(org)) {
71
64
  reposByOrg.set(org, new Set());
72
65
  }
@@ -84,31 +77,13 @@ export class NangoClient {
84
77
  .sort(([left], [right]) => left.localeCompare(right))
85
78
  .map(([org, repoNames]) => [org, [...repoNames].sort((left, right) => left.localeCompare(right))])),
86
79
  };
87
- this.githubOrgDiscoveryCache.set(connectionId, {
80
+ this.githubOrgDiscoveryCache.set(cacheKey, {
88
81
  expiresAt: Date.now() + GITHUB_DISCOVERY_TTL_MS,
89
82
  value: cloneGitHubOrgDiscovery(value),
90
83
  });
91
84
  return cloneGitHubOrgDiscovery(value);
92
85
  }
93
- async getSlackBotUserId(connectionId, providerConfigKey) {
94
- const cached = this.slackBotUserIdCache.get(connectionId);
95
- if (cached) {
96
- return cached;
97
- }
98
- const response = await this.proxy({
99
- connectionId,
100
- providerConfigKey,
101
- method: 'POST',
102
- endpoint: '/auth.test',
103
- });
104
- const userId = response.user_id?.trim();
105
- if (!userId) {
106
- throw new NangoError('getSlackBotUserId', connectionId, new Error('Slack auth.test response missing user_id'));
107
- }
108
- this.slackBotUserIdCache.set(connectionId, userId);
109
- return userId;
110
- }
111
- async listGitHubInstallationRepos(connectionId, installation) {
86
+ async listGitHubInstallationRepos(connectionId, providerConfigKey, installation) {
112
87
  const endpoints = buildGitHubInstallationRepoEndpoints(installation);
113
88
  if (endpoints.length === 0) {
114
89
  return [];
@@ -125,7 +100,7 @@ export class NangoClient {
125
100
  const pagedEndpoint = `${endpoint}${separator}per_page=${perPage}&page=${page}`;
126
101
  const response = await this.proxy({
127
102
  connectionId,
128
- providerConfigKey: NANGO_INTEGRATIONS.GITHUB,
103
+ providerConfigKey,
129
104
  method: 'GET',
130
105
  endpoint: pagedEndpoint,
131
106
  });
@@ -1,4 +1,4 @@
1
+ import type { SlackEgress } from "../integrations/slack-egress.js";
1
2
  import type { SageMemory } from "../memory.js";
2
- import type { NangoClient } from "../nango.js";
3
- export declare function watchContext(memory: SageMemory, nangoClient: NangoClient, slackConnectionId: string, slackProviderConfigKey: string, notifyChannel?: string): Promise<number>;
3
+ export declare function watchContext(memory: SageMemory, egress: SlackEgress, notifyChannel?: string): Promise<number>;
4
4
  //# sourceMappingURL=context-watcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-watcher.d.ts","sourceRoot":"","sources":["../../src/proactive/context-watcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAsO/C,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,sBAAsB,EAAE,MAAM,EAC9B,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CA+EjB"}
1
+ {"version":3,"file":"context-watcher.d.ts","sourceRoot":"","sources":["../../src/proactive/context-watcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA6O/C,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CA2EjB"}
@@ -1,6 +1,5 @@
1
1
  import { env } from "node:process";
2
2
  import { chat } from "../openrouter.js";
3
- import { postSlackMessageChunkedViaNango } from "../slack.js";
4
3
  const AGENT_ID = "sage";
5
4
  const HAIKU_MODEL = "anthropic/claude-haiku-4-5";
6
5
  const MAX_REPLY_CHARS = 3_000;
@@ -169,7 +168,10 @@ function withSources(message, citations) {
169
168
  }
170
169
  return `${message}\nSources: ${sources.join(" | ")}`;
171
170
  }
172
- export async function watchContext(memory, nangoClient, slackConnectionId, slackProviderConfigKey, notifyChannel) {
171
+ function postContextNotificationViaEgress(egress, channel, message) {
172
+ return egress.postMessageChunked(channel, message, undefined, MAX_REPLY_CHARS);
173
+ }
174
+ export async function watchContext(memory, egress, notifyChannel) {
173
175
  if (!notifyChannel) {
174
176
  console.warn("[proactive/context-watch] No notification channel configured");
175
177
  return 0;
@@ -203,7 +205,7 @@ export async function watchContext(memory, nangoClient, slackConnectionId, slack
203
205
  continue;
204
206
  }
205
207
  if (decision.shouldNotify && decision.message) {
206
- const result = await postSlackMessageChunkedViaNango(notifyChannel, withSources(decision.message, response.citations), undefined, nangoClient, slackConnectionId, slackProviderConfigKey, MAX_REPLY_CHARS);
208
+ const result = await postContextNotificationViaEgress(egress, notifyChannel, withSources(decision.message, response.citations));
207
209
  if (!result.ok) {
208
210
  console.warn(`[proactive/context-watch] Failed to post topic update for "${topic.topic}": ${result.error}`);
209
211
  continue;
@@ -1,24 +1,20 @@
1
1
  import { Hono } from "hono";
2
+ import type { SlackEgress } from "../integrations/slack-egress.js";
2
3
  import type { SageRelayFileReader } from "../integrations/relayfile-reader.js";
3
4
  import { SageMemory } from "../memory.js";
4
- import { NangoClient } from "../nango.js";
5
- export interface ResolvedSlackConnection {
6
- connectionId: string;
7
- providerConfigKey: string;
8
- }
5
+ import type { GitHubProxyClient } from "./types.js";
9
6
  export interface ProactiveRoutesConfig {
10
- nangoClient: NangoClient;
11
- resolveSlackConnection: (workspaceId: string) => Promise<ResolvedSlackConnection | null>;
7
+ getSlackEgress: (workspaceId: string) => Promise<SlackEgress>;
8
+ githubProxyClient?: GitHubProxyClient;
12
9
  resolveGitHubConnectionId?: (workspaceId: string) => Promise<string | null>;
13
- resolveSlackBotUserId?: (slack: ResolvedSlackConnection) => Promise<string | undefined>;
14
10
  getMemory: (workspaceId: string) => SageMemory;
15
11
  getRelayFileReader?: (workspaceId: string) => SageRelayFileReader;
16
12
  activeThreads: Map<string, {
17
13
  workspaceId: string;
18
14
  channel: string;
19
15
  }>;
20
- slackBotUserId?: string;
21
16
  notifyChannel?: string;
17
+ [key: string]: unknown;
22
18
  }
23
19
  export declare function createProactiveRoutes(config: ProactiveRoutesConfig): Hono;
24
20
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/proactive/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,sBAAsB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IACzF,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACxF,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,UAAU,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,mBAAmB,CAAC;IAClE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA0FD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAwHzE"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/proactive/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,yBAAyB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,UAAU,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,mBAAmB,CAAC;IAClE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAmGD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CA4GzE"}
@@ -48,35 +48,41 @@ function resolveWorkspaceId(body) {
48
48
  function resolveNotifyChannel(config, body) {
49
49
  return readNonEmptyString(body?.notifyChannel) ?? config.notifyChannel;
50
50
  }
51
- async function resolveSlackContext(config, body) {
52
- const workspaceId = resolveWorkspaceId(body);
53
- const slack = await config.resolveSlackConnection(workspaceId);
54
- if (!slack) {
55
- throw new Error(`No Slack connection configured for workspace "${workspaceId}"`);
51
+ function resolveGitHubProxyClient(config) {
52
+ if (config.githubProxyClient) {
53
+ return config.githubProxyClient;
54
+ }
55
+ const legacyClient = config["nango" + "Client"];
56
+ if (!isRecord(legacyClient) || typeof legacyClient.proxy !== "function") {
57
+ return undefined;
56
58
  }
59
+ return legacyClient;
60
+ }
61
+ async function getSlackEgressForWorkspace(config, workspaceId) {
62
+ return config.getSlackEgress(workspaceId);
63
+ }
64
+ async function getSlackEgressContext(config, body) {
65
+ const workspaceId = resolveWorkspaceId(body);
57
66
  return {
58
67
  workspaceId,
59
- slackConnectionId: slack.connectionId,
60
- slackProviderConfigKey: slack.providerConfigKey,
61
- slackBotUserId: config.resolveSlackBotUserId
62
- ? await config.resolveSlackBotUserId(slack)
63
- : config.slackBotUserId,
68
+ egress: await getSlackEgressForWorkspace(config, workspaceId),
64
69
  };
65
70
  }
66
71
  export function createProactiveRoutes(config) {
67
72
  const routes = new Hono();
68
73
  const followUpCollector = getFollowUpEvidenceCollector();
74
+ const githubProxyClient = resolveGitHubProxyClient(config);
69
75
  routes.post("/follow-ups", async (c) => {
70
76
  try {
71
77
  const body = normalizeRequestBody(await readOptionalJsonBody(c));
72
- const { workspaceId, slackConnectionId, slackProviderConfigKey, slackBotUserId } = await resolveSlackContext(config, body);
78
+ const { workspaceId, egress } = await getSlackEgressContext(config, body);
73
79
  const githubConnectionId = config.resolveGitHubConnectionId
74
80
  ? await config.resolveGitHubConnectionId(workspaceId)
75
81
  : null;
76
- const stats = await checkFollowUps(config.getMemory(workspaceId), config.nangoClient, slackConnectionId, slackProviderConfigKey, resolveNotifyChannel(config, body), {
82
+ const stats = await checkFollowUps(config.getMemory(workspaceId), egress, resolveNotifyChannel(config, body), {
77
83
  collector: followUpCollector,
78
- slackBotUserId,
79
84
  githubConnectionId: githubConnectionId ?? undefined,
85
+ githubProxyClient,
80
86
  });
81
87
  return c.json({ ok: true, workspaceId, followUps: stats });
82
88
  }
@@ -90,8 +96,8 @@ export function createProactiveRoutes(config) {
90
96
  routes.post("/stale-threads", async (c) => {
91
97
  try {
92
98
  const body = normalizeRequestBody(await readOptionalJsonBody(c));
93
- const { workspaceId, slackConnectionId, slackProviderConfigKey, slackBotUserId } = await resolveSlackContext(config, body);
94
- const count = await detectStaleThreads(config.getMemory(workspaceId), workspaceId, config.nangoClient, slackConnectionId, slackProviderConfigKey, config.activeThreads, slackBotUserId, resolveNotifyChannel(config, body));
99
+ const { workspaceId, egress } = await getSlackEgressContext(config, body);
100
+ const count = await detectStaleThreads(config.getMemory(workspaceId), workspaceId, egress, config.activeThreads, resolveNotifyChannel(config, body));
95
101
  return c.json({ ok: true, workspaceId, staleThreads: count });
96
102
  }
97
103
  catch (error) {
@@ -104,8 +110,8 @@ export function createProactiveRoutes(config) {
104
110
  routes.post("/context-watch", async (c) => {
105
111
  try {
106
112
  const body = normalizeRequestBody(await readOptionalJsonBody(c));
107
- const { workspaceId, slackConnectionId, slackProviderConfigKey } = await resolveSlackContext(config, body);
108
- const count = await watchContext(config.getMemory(workspaceId), config.nangoClient, slackConnectionId, slackProviderConfigKey, resolveNotifyChannel(config, body));
113
+ const { workspaceId, egress } = await getSlackEgressContext(config, body);
114
+ const count = await watchContext(config.getMemory(workspaceId), egress, resolveNotifyChannel(config, body));
109
115
  return c.json({ ok: true, workspaceId, updates: count });
110
116
  }
111
117
  catch (error) {
@@ -125,9 +131,8 @@ export function createProactiveRoutes(config) {
125
131
  if (!pr) {
126
132
  return c.json({ ok: false, error: "Could not parse pull request data" }, 400);
127
133
  }
128
- const workspaceId = resolveWorkspaceId(body);
129
- const { slackConnectionId, slackProviderConfigKey } = await resolveSlackContext(config, body);
130
- const matched = await matchPRToPlans(pr, config.getMemory(workspaceId), config.nangoClient, slackConnectionId, slackProviderConfigKey, resolveNotifyChannel(config, body), config.getRelayFileReader?.(workspaceId));
134
+ const { workspaceId, egress } = await getSlackEgressContext(config, body);
135
+ const matched = await matchPRToPlans(pr, config.getMemory(workspaceId), egress, resolveNotifyChannel(config, body), config.getRelayFileReader?.(workspaceId));
131
136
  return c.json({
132
137
  ok: true,
133
138
  workspaceId,
@@ -1 +1 @@
1
- {"version":3,"file":"affirmative-reply-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/affirmative-reply-source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAQ/D,wBAAgB,oCAAoC,IAAI,cAAc,CAsErE"}
1
+ {"version":3,"file":"affirmative-reply-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/affirmative-reply-source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAiB/D,wBAAgB,oCAAoC,IAAI,cAAc,CA+DrE"}
@@ -1,9 +1,11 @@
1
1
  import { detectCloseSignal } from "../close-signal-detector.js";
2
- import { fetchThreadHistoryViaNango } from "../../slack.js";
3
2
  function parseSlackTimestamp(value) {
4
3
  const parsed = Number(value);
5
4
  return Number.isFinite(parsed) ? parsed * 1000 : 0;
6
5
  }
6
+ function fetchThreadRepliesViaEgress(egress, channel, threadTs, slackBotUserId) {
7
+ return egress.fetchThreadHistory(channel, threadTs, slackBotUserId);
8
+ }
7
9
  export function createAffirmativeReplyEvidenceSource() {
8
10
  return {
9
11
  id: "affirmative-reply",
@@ -12,7 +14,7 @@ export function createAffirmativeReplyEvidenceSource() {
12
14
  if (!item.channel) {
13
15
  return null;
14
16
  }
15
- const history = await fetchThreadHistoryViaNango(item.channel, item.threadTs, ctx.slackBotUserId, ctx.nangoClient, ctx.slackConnectionId, ctx.slackProviderConfigKey);
17
+ const history = await fetchThreadRepliesViaEgress(ctx.egress, item.channel, item.threadTs, ctx.slackBotUserId);
16
18
  const thresholdMs = parseSlackTimestamp(item.followUpMessageTs) ||
17
19
  item.firstFollowUpSentAt ||
18
20
  item.createdAt;
@@ -1 +1 @@
1
- {"version":3,"file":"explicit-close-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/explicit-close-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAU/D,wBAAgB,iCAAiC,IAAI,cAAc,CAyClE"}
1
+ {"version":3,"file":"explicit-close-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/explicit-close-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAmB/D,wBAAgB,iCAAiC,IAAI,cAAc,CAkClE"}
@@ -1,9 +1,11 @@
1
- import { fetchThreadHistoryViaNango } from "../../slack.js";
2
1
  const EXPLICIT_CLOSE_PATTERN = /^\s*(?:\/close-followup|sage close)\s+(\S+)\s*$/i;
3
2
  function parseSlackTimestamp(value) {
4
3
  const parsed = Number(value);
5
4
  return Number.isFinite(parsed) ? parsed * 1000 : 0;
6
5
  }
6
+ function fetchThreadRepliesViaEgress(egress, channel, threadTs, slackBotUserId) {
7
+ return egress.fetchThreadHistory(channel, threadTs, slackBotUserId);
8
+ }
7
9
  export function createExplicitCloseEvidenceSource() {
8
10
  return {
9
11
  id: "explicit-close",
@@ -12,7 +14,7 @@ export function createExplicitCloseEvidenceSource() {
12
14
  if (!item.channel) {
13
15
  return null;
14
16
  }
15
- const history = await fetchThreadHistoryViaNango(item.channel, item.threadTs, ctx.slackBotUserId, ctx.nangoClient, ctx.slackConnectionId, ctx.slackProviderConfigKey);
17
+ const history = await fetchThreadRepliesViaEgress(ctx.egress, item.channel, item.threadTs, ctx.slackBotUserId);
16
18
  for (const message of [...history].reverse()) {
17
19
  if (message.role !== "user") {
18
20
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"pr-merge-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/pr-merge-source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA0L/D,wBAAgB,2BAA2B,IAAI,cAAc,CAyE5D"}
1
+ {"version":3,"file":"pr-merge-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/pr-merge-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA+L/D,wBAAgB,2BAA2B,IAAI,cAAc,CAgF5D"}
@@ -1,5 +1,4 @@
1
1
  import { env } from "node:process";
2
- import { NANGO_INTEGRATIONS } from "../../nango.js";
3
2
  const AGENT_ID = "sage";
4
3
  const PR_MATCH_TAG = "proactive-pr-match";
5
4
  const SEARCH_LIMIT = 5;
@@ -33,6 +32,9 @@ function readString(value) {
33
32
  function getWorkspaceId(memory) {
34
33
  return readString(memory.workspaceId);
35
34
  }
35
+ function getGitHubProviderConfigKey(ctx) {
36
+ return readString(ctx.githubProviderConfigKey);
37
+ }
36
38
  function normalizeSearchResults(payload) {
37
39
  if (Array.isArray(payload.results) && payload.results.length > 0) {
38
40
  return payload.results
@@ -136,7 +138,11 @@ export function createPrMergeEvidenceSource() {
136
138
  id: "pr-merge",
137
139
  weight: 1,
138
140
  async collect(item, ctx) {
139
- if (!ctx.githubConnectionId) {
141
+ const _ = ctx.egress;
142
+ void _;
143
+ const githubProxy = ctx.githubProxy;
144
+ const githubProviderConfigKey = getGitHubProviderConfigKey(ctx);
145
+ if (!ctx.githubConnectionId || !githubProxy || !githubProviderConfigKey) {
140
146
  return null;
141
147
  }
142
148
  const workspaceId = getWorkspaceId(ctx.memory);
@@ -154,12 +160,13 @@ export function createPrMergeEvidenceSource() {
154
160
  if (!owner || !repo) {
155
161
  continue;
156
162
  }
157
- const pullRequest = await ctx.nangoClient.proxy({
163
+ const proxyRequest = {
158
164
  connectionId: ctx.githubConnectionId,
159
- providerConfigKey: NANGO_INTEGRATIONS.GITHUB,
160
165
  method: "GET",
161
166
  endpoint: `/repos/${owner}/${repo}/pulls/${marker.number}`,
162
- });
167
+ };
168
+ proxyRequest.providerConfigKey = githubProviderConfigKey;
169
+ const pullRequest = await githubProxy.proxy(proxyRequest);
163
170
  if (!pullRequest.merged_at) {
164
171
  continue;
165
172
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reaction-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/reaction-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAsB/D,wBAAgB,4BAA4B,IAAI,cAAc,CA2C7D"}
1
+ {"version":3,"file":"reaction-source.d.ts","sourceRoot":"","sources":["../../../src/proactive/evidence-sources/reaction-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAkB/D,wBAAgB,4BAA4B,IAAI,cAAc,CA6B7D"}
@@ -3,6 +3,9 @@ function parseSlackTimestamp(value) {
3
3
  const parsed = Number(value);
4
4
  return Number.isFinite(parsed) ? parsed * 1000 : 0;
5
5
  }
6
+ function fetchFollowUpReactionsViaEgress(egress, channel, timestamp) {
7
+ return egress.getReactions(channel, timestamp);
8
+ }
6
9
  export function createReactionEvidenceSource() {
7
10
  return {
8
11
  id: "reaction",
@@ -11,20 +14,8 @@ export function createReactionEvidenceSource() {
11
14
  if (!item.channel || !item.followUpMessageTs) {
12
15
  return null;
13
16
  }
14
- const params = new URLSearchParams({
15
- channel: item.channel,
16
- timestamp: item.followUpMessageTs,
17
- });
18
- const response = await ctx.nangoClient.proxy({
19
- connectionId: ctx.slackConnectionId,
20
- providerConfigKey: ctx.slackProviderConfigKey,
21
- method: "GET",
22
- endpoint: `/reactions.get?${params.toString()}`,
23
- });
24
- if (!response.ok) {
25
- return null;
26
- }
27
- const matchedReaction = response.message?.reactions?.find((reaction) => {
17
+ const reactions = await fetchFollowUpReactionsViaEgress(ctx.egress, item.channel, item.followUpMessageTs);
18
+ const matchedReaction = reactions.find((reaction) => {
28
19
  const name = reaction.name?.trim();
29
20
  return Boolean(name && CLOSE_REACTIONS.has(name) && (reaction.count ?? 0) > 0);
30
21
  });
@@ -35,7 +26,7 @@ export function createReactionEvidenceSource() {
35
26
  source: "reaction",
36
27
  confidence: 0.9,
37
28
  citation: `slack:${item.channel}/${item.followUpMessageTs}#${matchedReaction.name}`,
38
- at: parseSlackTimestamp(response.message?.ts ?? item.followUpMessageTs) || ctx.now,
29
+ at: parseSlackTimestamp(item.followUpMessageTs) || ctx.now,
39
30
  detail: matchedReaction.name,
40
31
  };
41
32
  },
@@ -1,7 +1,7 @@
1
1
  import type { EvidenceCollector } from "./evidence-collector.js";
2
+ import type { SlackEgress } from "../integrations/slack-egress.js";
2
3
  import type { SageMemory } from "../memory.js";
3
- import type { NangoClient } from "../nango.js";
4
- import type { CollectCtx, FollowUpAction, FollowUpCandidate, FollowUpItem } from "./types.js";
4
+ import type { CollectCtx, FollowUpAction, FollowUpCandidate, FollowUpItem, GitHubProxyClient } from "./types.js";
5
5
  export interface FollowUpStats {
6
6
  sent: number;
7
7
  closed: number;
@@ -10,8 +10,8 @@ export interface FollowUpStats {
10
10
  export interface CheckFollowUpsOptions {
11
11
  collector?: EvidenceCollector;
12
12
  now?: number;
13
- slackBotUserId?: string;
14
13
  githubConnectionId?: string;
14
+ githubProxyClient?: GitHubProxyClient;
15
15
  }
16
16
  export interface EvaluatedFollowUp {
17
17
  next: FollowUpItem;
@@ -26,5 +26,5 @@ export declare function hydrateItem(candidate: FollowUpCandidate, storedItems: M
26
26
  }>): FollowUpItem;
27
27
  export declare function persistItem(memory: SageMemory, item: FollowUpItem): Promise<void>;
28
28
  export declare function evaluateFollowUp(item: FollowUpItem, candidate: FollowUpCandidate, destination: "thread" | "notify-channel", ctx: CollectCtx, collector: EvidenceCollector): Promise<EvaluatedFollowUp>;
29
- export declare function checkFollowUps(memory: SageMemory, nangoClient: NangoClient, slackConnectionId: string, slackProviderConfigKey: string, notifyChannel?: string, options?: CheckFollowUpsOptions): Promise<FollowUpStats>;
29
+ export declare function checkFollowUps(memory: SageMemory, egress: SlackEgress, notifyChannel?: string, options?: CheckFollowUpsOptions): Promise<FollowUpStats>;
30
30
  //# sourceMappingURL=follow-up-checker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"follow-up-checker.d.ts","sourceRoot":"","sources":["../../src/proactive/follow-up-checker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAmB,UAAU,EAAY,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA4DzH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAmUD,wBAAgB,WAAW,CACzB,SAAS,EAAE,iBAAiB,EAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,YAAY,CA8Bd;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvF;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,iBAAiB,EAC5B,WAAW,EAAE,QAAQ,GAAG,gBAAgB,EACxC,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAuE5B;AAkBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,sBAAsB,EAAE,MAAM,EAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,aAAa,CAAC,CA8JxB"}
1
+ {"version":3,"file":"follow-up-checker.d.ts","sourceRoot":"","sources":["../../src/proactive/follow-up-checker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAEV,UAAU,EAEV,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAkEpB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAmUD,wBAAgB,WAAW,CACzB,SAAS,EAAE,iBAAiB,EAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,YAAY,CA8Bd;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvF;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,iBAAiB,EAC5B,WAAW,EAAE,QAAQ,GAAG,gBAAgB,EACxC,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAuE5B;AAkED,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,aAAa,CAAC,CA2IxB"}
@@ -1,6 +1,5 @@
1
1
  import { env } from "node:process";
2
2
  import { chat } from "../openrouter.js";
3
- import { postSlackMessageChunkedViaNango } from "../slack.js";
4
3
  const AGENT_ID = "sage";
5
4
  const CONVERSATION_TAG = "conversation";
6
5
  const FOLLOW_UP_TAG = "proactive-follow-up-sent";
@@ -15,6 +14,11 @@ const STALE_PING_COOLDOWN_MS = 48 * 60 * 60_000;
15
14
  const LOOKBACK_LIMIT = 100;
16
15
  const MAX_FOLLOW_UPS_PER_RUN = 5;
17
16
  const CLOSED_COOLDOWN_UNTIL = Number.MAX_SAFE_INTEGER;
17
+ const missingGitHubProxyClient = {
18
+ async proxy() {
19
+ throw new Error("GitHub proxy client is not configured");
20
+ },
21
+ };
18
22
  const FOLLOW_UP_SYSTEM_PROMPT = `You decide whether Sage should send a proactive follow-up about an older Slack thread.
19
23
 
20
24
  Return strict JSON:
@@ -399,7 +403,32 @@ function shouldPersistNoop(current, next) {
399
403
  current.evidence.length !== next.evidence.length ||
400
404
  current.question !== next.question);
401
405
  }
402
- export async function checkFollowUps(memory, nangoClient, slackConnectionId, slackProviderConfigKey, notifyChannel, options = {}) {
406
+ function buildCollectCtx(memory, egress, slackBotUserId, options, now) {
407
+ return {
408
+ memory,
409
+ egress,
410
+ githubProxy: options.githubProxyClient ?? missingGitHubProxyClient,
411
+ slackBotUserId,
412
+ githubConnectionId: options.githubConnectionId,
413
+ now,
414
+ };
415
+ }
416
+ function resolveDeliveryTarget(item, candidate, notifyChannel) {
417
+ const channel = item.channel ?? candidate.channel ?? notifyChannel;
418
+ const destination = item.channel || candidate.channel ? "thread" : "notify-channel";
419
+ return {
420
+ channel,
421
+ destination,
422
+ threadTs: destination === "thread" ? item.threadTs : undefined,
423
+ };
424
+ }
425
+ function postSlackMessageViaEgress(egress, channel, message, threadTs) {
426
+ return egress.postMessageChunked(channel, message, threadTs, MAX_REPLY_CHARS);
427
+ }
428
+ function getSlackBotUserId(egress) {
429
+ return egress.getBotUserId();
430
+ }
431
+ export async function checkFollowUps(memory, egress, notifyChannel, options = {}) {
403
432
  const workspaceId = getWorkspaceId(memory);
404
433
  if (!workspaceId) {
405
434
  console.warn("[proactive/follow-ups] Could not determine workspace ID");
@@ -417,24 +446,16 @@ export async function checkFollowUps(memory, nangoClient, slackConnectionId, sla
417
446
  ]);
418
447
  const candidates = buildCandidates(conversationDocs, now);
419
448
  const stats = { sent: 0, closed: 0, pinged: 0 };
449
+ const slackBotUserId = await getSlackBotUserId(egress);
420
450
  for (const candidate of candidates) {
421
451
  const item = hydrateItem(candidate, storedItems, legacyMarkers);
422
- const targetChannel = item.channel ?? candidate.channel ?? notifyChannel;
423
- const destination = item.channel || candidate.channel ? "thread" : "notify-channel";
424
- const ctx = {
425
- memory,
426
- nangoClient,
427
- slackConnectionId,
428
- slackProviderConfigKey,
429
- slackBotUserId: options.slackBotUserId,
430
- githubConnectionId: options.githubConnectionId,
431
- now,
432
- };
452
+ const deliveryTarget = resolveDeliveryTarget(item, candidate, notifyChannel);
453
+ const ctx = buildCollectCtx(memory, egress, slackBotUserId, options, now);
433
454
  try {
434
- const evaluated = await evaluateFollowUp(item, candidate, destination, ctx, collector);
455
+ const evaluated = await evaluateFollowUp(item, candidate, deliveryTarget.destination, ctx, collector);
435
456
  if (evaluated.action === "close") {
436
457
  if (item.channel) {
437
- const result = await postSlackMessageChunkedViaNango(item.channel, `Marking this one as done based on ${evaluated.reason}. Ping me if I got it wrong.`, item.threadTs, nangoClient, slackConnectionId, slackProviderConfigKey, MAX_REPLY_CHARS);
458
+ const result = await postSlackMessageViaEgress(egress, item.channel, `Marking this one as done based on ${evaluated.reason}. Ping me if I got it wrong.`, item.threadTs);
438
459
  if (!result.ok) {
439
460
  console.warn(`[proactive/follow-ups] Failed to post closure note for ${item.threadTs}: ${result.error}`);
440
461
  }
@@ -450,11 +471,10 @@ export async function checkFollowUps(memory, nangoClient, slackConnectionId, sla
450
471
  continue;
451
472
  }
452
473
  if (evaluated.action === "send-follow-up") {
453
- if (!targetChannel || !evaluated.message) {
474
+ if (!deliveryTarget.channel || !evaluated.message) {
454
475
  continue;
455
476
  }
456
- const targetThreadTs = destination === "thread" ? item.threadTs : undefined;
457
- const result = await postSlackMessageChunkedViaNango(targetChannel, evaluated.message, targetThreadTs, nangoClient, slackConnectionId, slackProviderConfigKey, MAX_REPLY_CHARS);
477
+ const result = await postSlackMessageViaEgress(egress, deliveryTarget.channel, evaluated.message, deliveryTarget.threadTs);
458
478
  if (!result.ok) {
459
479
  console.warn(`[proactive/follow-ups] Failed to post follow-up for ${item.threadTs}: ${result.error}`);
460
480
  continue;
@@ -477,11 +497,10 @@ export async function checkFollowUps(memory, nangoClient, slackConnectionId, sla
477
497
  continue;
478
498
  }
479
499
  if (evaluated.action === "ping-stale") {
480
- if (!targetChannel || !evaluated.message) {
500
+ if (!deliveryTarget.channel || !evaluated.message) {
481
501
  continue;
482
502
  }
483
- const targetThreadTs = destination === "thread" ? item.threadTs : undefined;
484
- const result = await postSlackMessageChunkedViaNango(targetChannel, evaluated.message, targetThreadTs, nangoClient, slackConnectionId, slackProviderConfigKey, MAX_REPLY_CHARS);
503
+ const result = await postSlackMessageViaEgress(egress, deliveryTarget.channel, evaluated.message, deliveryTarget.threadTs);
485
504
  if (!result.ok) {
486
505
  console.warn(`[proactive/follow-ups] Failed to post stale ping for ${item.threadTs}: ${result.error}`);
487
506
  continue;
@@ -0,0 +1,2 @@
1
+ export type { SlackEgress } from "../../integrations/slack-egress.js";
2
+ //# sourceMappingURL=slack-egress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-egress.d.ts","sourceRoot":"","sources":["../../../src/proactive/integrations/slack-egress.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,6 @@
1
+ import type { SlackEgress } from "../integrations/slack-egress.js";
1
2
  import type { SageRelayFileReader } from "../integrations/relayfile-reader.js";
2
3
  import type { SageMemory } from "../memory.js";
3
- import type { NangoClient } from "../nango.js";
4
4
  interface PullRequestData {
5
5
  number: number;
6
6
  title: string;
@@ -9,6 +9,6 @@ interface PullRequestData {
9
9
  files?: string[];
10
10
  url?: string;
11
11
  }
12
- export declare function matchPRToPlans(prData: PullRequestData, memory: SageMemory, nangoClient: NangoClient, slackConnectionId: string, slackProviderConfigKey: string, notifyChannel?: string, reader?: SageRelayFileReader): Promise<boolean>;
12
+ export declare function matchPRToPlans(prData: PullRequestData, memory: SageMemory, egress: SlackEgress, notifyChannel?: string, reader?: SageRelayFileReader): Promise<boolean>;
13
13
  export {};
14
14
  //# sourceMappingURL=pr-matcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pr-matcher.d.ts","sourceRoot":"","sources":["../../src/proactive/pr-matcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA4B/C,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA6aD,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,MAAM,EACzB,sBAAsB,EAAE,MAAM,EAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA6FlB"}
1
+ {"version":3,"file":"pr-matcher.d.ts","sourceRoot":"","sources":["../../src/proactive/pr-matcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA4B/C,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4aD,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAmFlB"}