@inkeep/agents-core 0.0.0-dev-20260211235751 → 0.0.0-dev-20260212003026

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.
@@ -1,129 +0,0 @@
1
- import { getLogger } from "./logger.js";
2
- import { signJwt, verifyJwt } from "./jwt-helpers.js";
3
- import { z } from "zod";
4
-
5
- //#region src/utils/slack-user-token.ts
6
- const logger = getLogger("slack-user-token");
7
- const ISSUER = "inkeep-auth";
8
- const AUDIENCE = "inkeep-api";
9
- const TOKEN_USE = "slackUser";
10
- const ACTOR_SUB = "inkeep-work-app-slack";
11
- const TOKEN_TTL = "5m";
12
- /**
13
- * Zod schema for validating Slack user access token JWT payload.
14
- * This is the canonical schema from the work_apps_slack spec.
15
- */
16
- const SlackAccessTokenPayloadSchema = z.object({
17
- iss: z.literal(ISSUER),
18
- aud: z.literal(AUDIENCE),
19
- sub: z.string().min(1),
20
- iat: z.number(),
21
- exp: z.number(),
22
- jti: z.string().optional(),
23
- tokenUse: z.literal(TOKEN_USE),
24
- act: z.object({ sub: z.literal(ACTOR_SUB) }),
25
- tenantId: z.string().min(1),
26
- slack: z.object({
27
- teamId: z.string().min(1),
28
- userId: z.string().min(1),
29
- enterpriseId: z.string().min(1).optional(),
30
- email: z.string().email().optional()
31
- })
32
- });
33
- /**
34
- * Sign a Slack user JWT token for calling Manage/Run APIs.
35
- * Token expires in 5 minutes.
36
- *
37
- * This token is used when Slack runtime logic needs to call:
38
- * - Manage API (list projects, list agents)
39
- * - Run API (POST /run/api/chat)
40
- */
41
- async function signSlackUserToken(params) {
42
- try {
43
- const token = await signJwt({
44
- issuer: ISSUER,
45
- subject: params.inkeepUserId,
46
- audience: AUDIENCE,
47
- expiresIn: TOKEN_TTL,
48
- claims: {
49
- tokenUse: TOKEN_USE,
50
- act: { sub: ACTOR_SUB },
51
- tenantId: params.tenantId,
52
- slack: {
53
- teamId: params.slackTeamId,
54
- userId: params.slackUserId,
55
- ...params.slackEnterpriseId && { enterpriseId: params.slackEnterpriseId },
56
- ...params.slackEmail && { email: params.slackEmail }
57
- }
58
- }
59
- });
60
- logger.debug({
61
- inkeepUserId: params.inkeepUserId,
62
- tenantId: params.tenantId,
63
- slackTeamId: params.slackTeamId,
64
- slackUserId: params.slackUserId
65
- }, "Generated Slack user token");
66
- return token;
67
- } catch (error) {
68
- const errorMessage = error instanceof Error ? error.message : String(error);
69
- logger.error({
70
- error,
71
- errorMessage
72
- }, "Failed to generate Slack user token");
73
- throw new Error(`Failed to generate Slack user token: ${errorMessage}`);
74
- }
75
- }
76
- /**
77
- * Verify and decode a Slack user JWT token.
78
- * Validates signature, expiration, issuer, audience, and schema.
79
- */
80
- async function verifySlackUserToken(token) {
81
- const result = await verifyJwt(token, {
82
- issuer: ISSUER,
83
- audience: AUDIENCE
84
- });
85
- if (!result.valid || !result.payload) {
86
- logger.warn({ error: result.error }, "Slack user token verification failed");
87
- return {
88
- valid: false,
89
- error: result.error
90
- };
91
- }
92
- const parseResult = SlackAccessTokenPayloadSchema.safeParse(result.payload);
93
- if (!parseResult.success) {
94
- logger.warn({
95
- payload: result.payload,
96
- issues: parseResult.error.issues
97
- }, "Invalid Slack user token: schema validation failed");
98
- return {
99
- valid: false,
100
- error: `Invalid token schema: ${parseResult.error.issues.map((e) => e.message).join(", ")}`
101
- };
102
- }
103
- logger.debug({
104
- inkeepUserId: parseResult.data.sub,
105
- tenantId: parseResult.data.tenantId,
106
- slackTeamId: parseResult.data.slack.teamId
107
- }, "Successfully verified Slack user token");
108
- return {
109
- valid: true,
110
- payload: parseResult.data
111
- };
112
- }
113
- /**
114
- * Check if a token looks like a Slack user JWT (quick check before full verification).
115
- * Returns true if the token has the expected issuer and tokenUse.
116
- */
117
- function isSlackUserToken(token) {
118
- try {
119
- const parts = token.split(".");
120
- if (parts.length !== 3) return false;
121
- const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
122
- return payload?.iss === ISSUER && payload?.tokenUse === TOKEN_USE;
123
- } catch {
124
- return false;
125
- }
126
- }
127
-
128
- //#endregion
129
- export { SlackAccessTokenPayloadSchema, isSlackUserToken, signSlackUserToken, verifySlackUserToken };
@@ -1,35 +0,0 @@
1
- //#region src/utils/sse-parser.d.ts
2
- /**
3
- * SSE (Server-Sent Events) Response Parser
4
- *
5
- * Shared utility for parsing SSE responses from the chat API.
6
- * Used by EvaluationService, Slack integration, and other consumers.
7
- *
8
- * Handles multiple response formats:
9
- * - OpenAI-compatible chat completion chunks
10
- * - Vercel AI SDK data stream format (text-delta)
11
- * - Error operations and events
12
- */
13
- interface ParsedSSEResponse {
14
- text: string;
15
- error?: string;
16
- }
17
- /**
18
- * Parse SSE (Server-Sent Events) response from chat API
19
- * Handles text deltas, error operations, and other data operations
20
- *
21
- * Supports:
22
- * - OpenAI-compatible format: `chat.completion.chunk` with `delta.content`
23
- * - Vercel AI SDK format: `text-delta` with `delta`
24
- * - Vercel AI SDK format: `text-start` and `text-end` markers (ignored)
25
- * - Error operations: `data-operation` with `type: 'error'`
26
- * - Direct error events: `type: 'error'`
27
- *
28
- * Ignores:
29
- * - `data-operation` events (metadata, not content)
30
- * - `text-start` and `text-end` markers
31
- * - `[DONE]` markers
32
- */
33
- declare function parseSSEResponse(sseText: string): ParsedSSEResponse;
34
- //#endregion
35
- export { ParsedSSEResponse, parseSSEResponse };
@@ -1,71 +0,0 @@
1
- //#region src/utils/sse-parser.ts
2
- /**
3
- * Parse SSE (Server-Sent Events) response from chat API
4
- * Handles text deltas, error operations, and other data operations
5
- *
6
- * Supports:
7
- * - OpenAI-compatible format: `chat.completion.chunk` with `delta.content`
8
- * - Vercel AI SDK format: `text-delta` with `delta`
9
- * - Vercel AI SDK format: `text-start` and `text-end` markers (ignored)
10
- * - Error operations: `data-operation` with `type: 'error'`
11
- * - Direct error events: `type: 'error'`
12
- *
13
- * Ignores:
14
- * - `data-operation` events (metadata, not content)
15
- * - `text-start` and `text-end` markers
16
- * - `[DONE]` markers
17
- */
18
- function parseSSEResponse(sseText) {
19
- let textContent = "";
20
- let hasError = false;
21
- let errorMessage = "";
22
- const lines = sseText.split("\n").filter((line) => line.startsWith("data: "));
23
- for (const line of lines) {
24
- const jsonStr = line.slice(6).trim();
25
- if (!jsonStr || jsonStr === "[DONE]") continue;
26
- try {
27
- const data = JSON.parse(jsonStr);
28
- if (data.object === "chat.completion.chunk" && data.choices?.[0]?.delta) {
29
- const delta = data.choices[0].delta;
30
- if (delta.content && typeof delta.content === "string") try {
31
- const parsedContent = JSON.parse(delta.content);
32
- if (parsedContent.type === "data-operation") {
33
- if (parsedContent.data?.type === "error") {
34
- hasError = true;
35
- errorMessage = parsedContent.data.message || "Unknown error occurred";
36
- }
37
- continue;
38
- }
39
- textContent += delta.content;
40
- } catch {
41
- textContent += delta.content;
42
- }
43
- continue;
44
- }
45
- if (data.type === "text-delta" && data.delta) {
46
- textContent += data.delta;
47
- continue;
48
- }
49
- if (data.type === "text-start" || data.type === "text-end") continue;
50
- if (data.type === "data-operation") {
51
- if (data.data?.type === "error") {
52
- hasError = true;
53
- errorMessage = data.data.message || "Unknown error occurred";
54
- }
55
- continue;
56
- }
57
- if (data.type === "error") {
58
- hasError = true;
59
- errorMessage = data.message || "Unknown error occurred";
60
- }
61
- } catch {}
62
- }
63
- if (hasError) return {
64
- text: textContent.trim(),
65
- error: errorMessage
66
- };
67
- return { text: textContent.trim() };
68
- }
69
-
70
- //#endregion
71
- export { parseSSEResponse };
@@ -1,114 +0,0 @@
1
- CREATE TABLE "work_app_slack_channel_agent_configs" (
2
- "id" varchar(256) PRIMARY KEY NOT NULL,
3
- "tenant_id" varchar(256) NOT NULL,
4
- "slack_team_id" varchar(256) NOT NULL,
5
- "slack_channel_id" varchar(256) NOT NULL,
6
- "slack_channel_name" varchar(256),
7
- "slack_channel_type" varchar(50),
8
- "project_id" varchar(256) NOT NULL,
9
- "agent_id" varchar(256) NOT NULL,
10
- "agent_name" varchar(256),
11
- "configured_by_user_id" text,
12
- "enabled" boolean DEFAULT true NOT NULL,
13
- "created_at" timestamp DEFAULT now() NOT NULL,
14
- "updated_at" timestamp DEFAULT now() NOT NULL,
15
- CONSTRAINT "work_app_slack_channel_agent_configs_unique" UNIQUE("tenant_id","slack_team_id","slack_channel_id")
16
- );
17
- --> statement-breakpoint
18
- CREATE TABLE "work_app_slack_user_mappings" (
19
- "id" varchar(256) PRIMARY KEY NOT NULL,
20
- "tenant_id" varchar(256) NOT NULL,
21
- "client_id" varchar(256) DEFAULT 'work-apps-slack' NOT NULL,
22
- "slack_user_id" varchar(256) NOT NULL,
23
- "slack_team_id" varchar(256) NOT NULL,
24
- "slack_enterprise_id" varchar(256),
25
- "inkeep_user_id" text NOT NULL,
26
- "slack_username" varchar(256),
27
- "slack_email" varchar(256),
28
- "linked_at" timestamp DEFAULT now() NOT NULL,
29
- "last_used_at" timestamp,
30
- "created_at" timestamp DEFAULT now() NOT NULL,
31
- "updated_at" timestamp DEFAULT now() NOT NULL,
32
- CONSTRAINT "work_app_slack_user_mappings_unique" UNIQUE("tenant_id","client_id","slack_team_id","slack_user_id")
33
- );
34
- --> statement-breakpoint
35
- CREATE TABLE "work_app_slack_workspaces" (
36
- "id" varchar(256) PRIMARY KEY NOT NULL,
37
- "tenant_id" varchar(256) NOT NULL,
38
- "slack_team_id" varchar(256) NOT NULL,
39
- "slack_enterprise_id" varchar(256),
40
- "slack_app_id" varchar(256),
41
- "slack_team_name" varchar(512),
42
- "nango_provider_config_key" varchar(256) DEFAULT 'work-apps-slack' NOT NULL,
43
- "nango_connection_id" varchar(256) NOT NULL,
44
- "status" varchar(20) DEFAULT 'active' NOT NULL,
45
- "installed_by_user_id" text,
46
- "created_at" timestamp DEFAULT now() NOT NULL,
47
- "updated_at" timestamp DEFAULT now() NOT NULL,
48
- CONSTRAINT "work_app_slack_workspaces_tenant_team_unique" UNIQUE("tenant_id","slack_team_id"),
49
- CONSTRAINT "work_app_slack_workspaces_nango_connection_unique" UNIQUE("nango_connection_id")
50
- );
51
- --> statement-breakpoint
52
- /*
53
- Unfortunately in current drizzle-kit version we can't automatically get name for primary key.
54
- We are working on making it available!
55
-
56
- Meanwhile you can:
57
- 1. Check pk name in your database, by running
58
- SELECT constraint_name FROM information_schema.table_constraints
59
- WHERE table_schema = 'public'
60
- AND table_name = 'work_app_github_installations'
61
- AND constraint_type = 'PRIMARY KEY';
62
- 2. Uncomment code below and paste pk name manually
63
-
64
- Hope to release this update as soon as possible
65
- */
66
-
67
- -- ALTER TABLE "work_app_github_installations" DROP CONSTRAINT "<constraint_name>";--> statement-breakpoint
68
- /*
69
- Unfortunately in current drizzle-kit version we can't automatically get name for primary key.
70
- We are working on making it available!
71
-
72
- Meanwhile you can:
73
- 1. Check pk name in your database, by running
74
- SELECT constraint_name FROM information_schema.table_constraints
75
- WHERE table_schema = 'public'
76
- AND table_name = 'work_app_github_mcp_tool_repository_access'
77
- AND constraint_type = 'PRIMARY KEY';
78
- 2. Uncomment code below and paste pk name manually
79
-
80
- Hope to release this update as soon as possible
81
- */
82
-
83
- -- ALTER TABLE "work_app_github_mcp_tool_repository_access" DROP CONSTRAINT "<constraint_name>";--> statement-breakpoint
84
- /*
85
- Unfortunately in current drizzle-kit version we can't automatically get name for primary key.
86
- We are working on making it available!
87
-
88
- Meanwhile you can:
89
- 1. Check pk name in your database, by running
90
- SELECT constraint_name FROM information_schema.table_constraints
91
- WHERE table_schema = 'public'
92
- AND table_name = 'work_app_github_project_repository_access'
93
- AND constraint_type = 'PRIMARY KEY';
94
- 2. Uncomment code below and paste pk name manually
95
-
96
- Hope to release this update as soon as possible
97
- */
98
-
99
- -- ALTER TABLE "work_app_github_project_repository_access" DROP CONSTRAINT "<constraint_name>";--> statement-breakpoint
100
- ALTER TABLE "work_app_slack_channel_agent_configs" ADD CONSTRAINT "work_app_slack_channel_agent_configs_tenant_id_organization_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
101
- ALTER TABLE "work_app_slack_channel_agent_configs" ADD CONSTRAINT "work_app_slack_channel_agent_configs_configured_by_user_id_user_id_fk" FOREIGN KEY ("configured_by_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
102
- ALTER TABLE "work_app_slack_user_mappings" ADD CONSTRAINT "work_app_slack_user_mappings_tenant_id_organization_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
103
- ALTER TABLE "work_app_slack_user_mappings" ADD CONSTRAINT "work_app_slack_user_mappings_inkeep_user_id_user_id_fk" FOREIGN KEY ("inkeep_user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
104
- ALTER TABLE "work_app_slack_workspaces" ADD CONSTRAINT "work_app_slack_workspaces_tenant_id_organization_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
105
- ALTER TABLE "work_app_slack_workspaces" ADD CONSTRAINT "work_app_slack_workspaces_installed_by_user_id_user_id_fk" FOREIGN KEY ("installed_by_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
106
- CREATE INDEX "work_app_slack_channel_agent_configs_tenant_idx" ON "work_app_slack_channel_agent_configs" USING btree ("tenant_id");--> statement-breakpoint
107
- CREATE INDEX "work_app_slack_channel_agent_configs_team_idx" ON "work_app_slack_channel_agent_configs" USING btree ("slack_team_id");--> statement-breakpoint
108
- CREATE INDEX "work_app_slack_channel_agent_configs_channel_idx" ON "work_app_slack_channel_agent_configs" USING btree ("slack_channel_id");--> statement-breakpoint
109
- CREATE INDEX "work_app_slack_user_mappings_tenant_idx" ON "work_app_slack_user_mappings" USING btree ("tenant_id");--> statement-breakpoint
110
- CREATE INDEX "work_app_slack_user_mappings_user_idx" ON "work_app_slack_user_mappings" USING btree ("inkeep_user_id");--> statement-breakpoint
111
- CREATE INDEX "work_app_slack_user_mappings_team_idx" ON "work_app_slack_user_mappings" USING btree ("slack_team_id");--> statement-breakpoint
112
- CREATE INDEX "work_app_slack_user_mappings_slack_user_idx" ON "work_app_slack_user_mappings" USING btree ("slack_user_id");--> statement-breakpoint
113
- CREATE INDEX "work_app_slack_workspaces_tenant_idx" ON "work_app_slack_workspaces" USING btree ("tenant_id");--> statement-breakpoint
114
- CREATE INDEX "work_app_slack_workspaces_team_idx" ON "work_app_slack_workspaces" USING btree ("slack_team_id");