@inkeep/agents-core 0.47.4 → 0.48.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.
- package/README.md +1 -1
- package/dist/auth/auth-validation-schemas.d.ts +17 -17
- package/dist/auth/auth.d.ts +1 -1
- package/dist/client-exports.d.ts +13 -2
- package/dist/client-exports.js +5 -4
- package/dist/data-access/index.d.ts +6 -1
- package/dist/data-access/index.js +6 -1
- package/dist/data-access/manage/agentFull.js +154 -1
- package/dist/data-access/manage/agents.d.ts +4 -4
- package/dist/data-access/manage/agents.js +56 -4
- package/dist/data-access/manage/artifactComponents.d.ts +41 -5
- package/dist/data-access/manage/dataComponents.d.ts +2 -2
- package/dist/data-access/manage/functionTools.d.ts +3 -3
- package/dist/data-access/manage/projectFull.js +97 -0
- package/dist/data-access/manage/scheduledTriggers.d.ts +80 -0
- package/dist/data-access/manage/scheduledTriggers.js +76 -0
- package/dist/data-access/manage/scheduledWorkflows.d.ts +29 -0
- package/dist/data-access/manage/scheduledWorkflows.js +32 -0
- package/dist/data-access/manage/skills.d.ts +109 -0
- package/dist/data-access/manage/skills.js +122 -0
- package/dist/data-access/manage/subAgentRelations.d.ts +6 -6
- package/dist/data-access/manage/tools.d.ts +4 -4
- package/dist/data-access/manage/triggers.d.ts +2 -2
- package/dist/data-access/runtime/conversations.d.ts +4 -4
- package/dist/data-access/runtime/scheduledTriggerInvocations.d.ts +233 -0
- package/dist/data-access/runtime/scheduledTriggerInvocations.js +226 -0
- package/dist/data-access/runtime/tasks.d.ts +2 -2
- package/dist/data-access/runtime/workAppSlack.d.ts +55 -0
- package/dist/data-access/runtime/workAppSlack.js +146 -0
- package/dist/db/manage/manage-schema.d.ts +1440 -510
- package/dist/db/manage/manage-schema.js +240 -15
- package/dist/db/runtime/runtime-schema.d.ts +1236 -234
- package/dist/db/runtime/runtime-schema.js +108 -3
- package/dist/index.d.ts +15 -6
- package/dist/index.js +13 -5
- package/dist/types/entities.d.ts +15 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/utils/index.d.ts +5 -2
- package/dist/utils/index.js +5 -2
- package/dist/utils/slack-link-token.d.ts +57 -0
- package/dist/utils/slack-link-token.js +112 -0
- package/dist/utils/slack-user-token.d.ts +65 -0
- package/dist/utils/slack-user-token.js +129 -0
- package/dist/utils/sse-parser.d.ts +35 -0
- package/dist/utils/sse-parser.js +71 -0
- package/dist/utils/tracer-factory.d.ts +11 -2
- package/dist/utils/tracer-factory.js +24 -5
- package/dist/utils/tracer.d.ts +2 -2
- package/dist/utils/tracer.js +2 -2
- package/dist/utils/trigger-auth.d.ts +1 -1
- package/dist/validation/drizzle-schema-helpers.d.ts +3 -3
- package/dist/validation/extend-schemas.d.ts +34 -0
- package/dist/validation/extend-schemas.js +33 -0
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +2 -2
- package/dist/validation/json-schemas.d.ts +28 -0
- package/dist/validation/json-schemas.js +56 -0
- package/dist/validation/schemas.d.ts +5875 -2585
- package/dist/validation/schemas.js +159 -38
- package/dist/validation/stream-event-schemas.d.ts +0 -2
- package/dist/validation/stream-event-schemas.js +1 -2
- package/drizzle/manage/0007_nice_lilandra.sql +3 -0
- package/drizzle/manage/0008_friendly_mentallo.sql +32 -0
- package/drizzle/manage/0009_chilly_old_lace.sql +39 -0
- package/drizzle/manage/meta/0007_snapshot.json +3148 -0
- package/drizzle/manage/meta/0008_snapshot.json +3391 -0
- package/drizzle/manage/meta/0009_snapshot.json +3670 -0
- package/drizzle/manage/meta/_journal.json +21 -0
- package/drizzle/runtime/0012_greedy_hulk.sql +84 -0
- package/drizzle/runtime/0013_huge_white_queen.sql +19 -0
- package/drizzle/runtime/meta/0007_snapshot.json +1 -1
- package/drizzle/runtime/meta/0012_snapshot.json +3622 -0
- package/drizzle/runtime/meta/0013_snapshot.json +3746 -0
- package/drizzle/runtime/meta/_journal.json +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { JwtVerifyResult } from "./jwt-helpers.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/slack-link-token.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Zod schema for validating Slack link token JWT payload.
|
|
8
|
+
* This is a stateless token used for the Slack-to-Inkeep account linking flow.
|
|
9
|
+
* When a user runs `/inkeep link` in Slack, this JWT is generated and embedded
|
|
10
|
+
* in a URL that the user visits to complete the linking.
|
|
11
|
+
*/
|
|
12
|
+
declare const SlackLinkTokenPayloadSchema: z.ZodObject<{
|
|
13
|
+
iss: z.ZodLiteral<"inkeep-auth">;
|
|
14
|
+
aud: z.ZodLiteral<"slack-link">;
|
|
15
|
+
sub: z.ZodString;
|
|
16
|
+
iat: z.ZodNumber;
|
|
17
|
+
exp: z.ZodNumber;
|
|
18
|
+
jti: z.ZodOptional<z.ZodString>;
|
|
19
|
+
tokenUse: z.ZodLiteral<"slackLinkCode">;
|
|
20
|
+
tenantId: z.ZodString;
|
|
21
|
+
slack: z.ZodObject<{
|
|
22
|
+
teamId: z.ZodString;
|
|
23
|
+
userId: z.ZodString;
|
|
24
|
+
enterpriseId: z.ZodOptional<z.ZodString>;
|
|
25
|
+
username: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
type SlackLinkTokenPayload = z.infer<typeof SlackLinkTokenPayloadSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* Parameters for generating a Slack link token
|
|
31
|
+
*/
|
|
32
|
+
interface SignSlackLinkTokenParams {
|
|
33
|
+
tenantId: string;
|
|
34
|
+
slackTeamId: string;
|
|
35
|
+
slackUserId: string;
|
|
36
|
+
slackEnterpriseId?: string;
|
|
37
|
+
slackUsername?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Result of verifying a Slack link token
|
|
41
|
+
*/
|
|
42
|
+
type VerifySlackLinkTokenResult = JwtVerifyResult<SlackLinkTokenPayload>;
|
|
43
|
+
/**
|
|
44
|
+
* Sign a Slack link JWT token for the device authorization flow.
|
|
45
|
+
* Token expires in 10 minutes.
|
|
46
|
+
*
|
|
47
|
+
* This token is generated when a user runs `/inkeep link` in Slack
|
|
48
|
+
* and is verified when they visit the dashboard link page.
|
|
49
|
+
*/
|
|
50
|
+
declare function signSlackLinkToken(params: SignSlackLinkTokenParams): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Verify and decode a Slack link JWT token.
|
|
53
|
+
* Validates signature, expiration, issuer, audience, and schema.
|
|
54
|
+
*/
|
|
55
|
+
declare function verifySlackLinkToken(token: string): Promise<VerifySlackLinkTokenResult>;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { SignSlackLinkTokenParams, SlackLinkTokenPayload, SlackLinkTokenPayloadSchema, VerifySlackLinkTokenResult, signSlackLinkToken, verifySlackLinkToken };
|
|
@@ -0,0 +1,112 @@
|
|
|
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-link-token.ts
|
|
6
|
+
const logger = getLogger("slack-link-token");
|
|
7
|
+
const ISSUER = "inkeep-auth";
|
|
8
|
+
const AUDIENCE = "slack-link";
|
|
9
|
+
const TOKEN_USE = "slackLinkCode";
|
|
10
|
+
const TOKEN_TTL = "10m";
|
|
11
|
+
/**
|
|
12
|
+
* Zod schema for validating Slack link token JWT payload.
|
|
13
|
+
* This is a stateless token used for the Slack-to-Inkeep account linking flow.
|
|
14
|
+
* When a user runs `/inkeep link` in Slack, this JWT is generated and embedded
|
|
15
|
+
* in a URL that the user visits to complete the linking.
|
|
16
|
+
*/
|
|
17
|
+
const SlackLinkTokenPayloadSchema = z.object({
|
|
18
|
+
iss: z.literal(ISSUER),
|
|
19
|
+
aud: z.literal(AUDIENCE),
|
|
20
|
+
sub: z.string().min(1),
|
|
21
|
+
iat: z.number(),
|
|
22
|
+
exp: z.number(),
|
|
23
|
+
jti: z.string().optional(),
|
|
24
|
+
tokenUse: z.literal(TOKEN_USE),
|
|
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
|
+
username: z.string().optional()
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Sign a Slack link JWT token for the device authorization flow.
|
|
35
|
+
* Token expires in 10 minutes.
|
|
36
|
+
*
|
|
37
|
+
* This token is generated when a user runs `/inkeep link` in Slack
|
|
38
|
+
* and is verified when they visit the dashboard link page.
|
|
39
|
+
*/
|
|
40
|
+
async function signSlackLinkToken(params) {
|
|
41
|
+
try {
|
|
42
|
+
const token = await signJwt({
|
|
43
|
+
issuer: ISSUER,
|
|
44
|
+
subject: `slack:${params.slackTeamId}:${params.slackUserId}`,
|
|
45
|
+
audience: AUDIENCE,
|
|
46
|
+
expiresIn: TOKEN_TTL,
|
|
47
|
+
claims: {
|
|
48
|
+
tokenUse: TOKEN_USE,
|
|
49
|
+
tenantId: params.tenantId,
|
|
50
|
+
slack: {
|
|
51
|
+
teamId: params.slackTeamId,
|
|
52
|
+
userId: params.slackUserId,
|
|
53
|
+
...params.slackEnterpriseId && { enterpriseId: params.slackEnterpriseId },
|
|
54
|
+
...params.slackUsername && { username: params.slackUsername }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
logger.debug({
|
|
59
|
+
tenantId: params.tenantId,
|
|
60
|
+
slackTeamId: params.slackTeamId,
|
|
61
|
+
slackUserId: params.slackUserId
|
|
62
|
+
}, "Generated Slack link token");
|
|
63
|
+
return token;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
66
|
+
logger.error({
|
|
67
|
+
error,
|
|
68
|
+
errorMessage
|
|
69
|
+
}, "Failed to generate Slack link token");
|
|
70
|
+
throw new Error(`Failed to generate Slack link token: ${errorMessage}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Verify and decode a Slack link JWT token.
|
|
75
|
+
* Validates signature, expiration, issuer, audience, and schema.
|
|
76
|
+
*/
|
|
77
|
+
async function verifySlackLinkToken(token) {
|
|
78
|
+
const result = await verifyJwt(token, {
|
|
79
|
+
issuer: ISSUER,
|
|
80
|
+
audience: AUDIENCE
|
|
81
|
+
});
|
|
82
|
+
if (!result.valid || !result.payload) {
|
|
83
|
+
logger.warn({ error: result.error }, "Slack link token verification failed");
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
error: result.error
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const parseResult = SlackLinkTokenPayloadSchema.safeParse(result.payload);
|
|
90
|
+
if (!parseResult.success) {
|
|
91
|
+
logger.warn({
|
|
92
|
+
payload: result.payload,
|
|
93
|
+
issues: parseResult.error.issues
|
|
94
|
+
}, "Invalid Slack link token: schema validation failed");
|
|
95
|
+
return {
|
|
96
|
+
valid: false,
|
|
97
|
+
error: `Invalid token schema: ${parseResult.error.issues.map((e) => e.message).join(", ")}`
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
logger.debug({
|
|
101
|
+
tenantId: parseResult.data.tenantId,
|
|
102
|
+
slackTeamId: parseResult.data.slack.teamId,
|
|
103
|
+
slackUserId: parseResult.data.slack.userId
|
|
104
|
+
}, "Successfully verified Slack link token");
|
|
105
|
+
return {
|
|
106
|
+
valid: true,
|
|
107
|
+
payload: parseResult.data
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//#endregion
|
|
112
|
+
export { SlackLinkTokenPayloadSchema, signSlackLinkToken, verifySlackLinkToken };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { JwtVerifyResult } from "./jwt-helpers.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/slack-user-token.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Zod schema for validating Slack user access token JWT payload.
|
|
8
|
+
* This is the canonical schema from the work_apps_slack spec.
|
|
9
|
+
*/
|
|
10
|
+
declare const SlackAccessTokenPayloadSchema: z.ZodObject<{
|
|
11
|
+
iss: z.ZodLiteral<"inkeep-auth">;
|
|
12
|
+
aud: z.ZodLiteral<"inkeep-api">;
|
|
13
|
+
sub: z.ZodString;
|
|
14
|
+
iat: z.ZodNumber;
|
|
15
|
+
exp: z.ZodNumber;
|
|
16
|
+
jti: z.ZodOptional<z.ZodString>;
|
|
17
|
+
tokenUse: z.ZodLiteral<"slackUser">;
|
|
18
|
+
act: z.ZodObject<{
|
|
19
|
+
sub: z.ZodLiteral<"inkeep-work-app-slack">;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
tenantId: z.ZodString;
|
|
22
|
+
slack: z.ZodObject<{
|
|
23
|
+
teamId: z.ZodString;
|
|
24
|
+
userId: z.ZodString;
|
|
25
|
+
enterpriseId: z.ZodOptional<z.ZodString>;
|
|
26
|
+
email: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
type SlackAccessTokenPayload = z.infer<typeof SlackAccessTokenPayloadSchema>;
|
|
30
|
+
/**
|
|
31
|
+
* Parameters for generating a Slack user token
|
|
32
|
+
*/
|
|
33
|
+
interface SignSlackUserTokenParams {
|
|
34
|
+
inkeepUserId: string;
|
|
35
|
+
tenantId: string;
|
|
36
|
+
slackTeamId: string;
|
|
37
|
+
slackUserId: string;
|
|
38
|
+
slackEnterpriseId?: string;
|
|
39
|
+
slackEmail?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result of verifying a Slack user token
|
|
43
|
+
*/
|
|
44
|
+
type VerifySlackUserTokenResult = JwtVerifyResult<SlackAccessTokenPayload>;
|
|
45
|
+
/**
|
|
46
|
+
* Sign a Slack user JWT token for calling Manage/Run APIs.
|
|
47
|
+
* Token expires in 5 minutes.
|
|
48
|
+
*
|
|
49
|
+
* This token is used when Slack runtime logic needs to call:
|
|
50
|
+
* - Manage API (list projects, list agents)
|
|
51
|
+
* - Run API (POST /run/api/chat)
|
|
52
|
+
*/
|
|
53
|
+
declare function signSlackUserToken(params: SignSlackUserTokenParams): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Verify and decode a Slack user JWT token.
|
|
56
|
+
* Validates signature, expiration, issuer, audience, and schema.
|
|
57
|
+
*/
|
|
58
|
+
declare function verifySlackUserToken(token: string): Promise<VerifySlackUserTokenResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if a token looks like a Slack user JWT (quick check before full verification).
|
|
61
|
+
* Returns true if the token has the expected issuer and tokenUse.
|
|
62
|
+
*/
|
|
63
|
+
declare function isSlackUserToken(token: string): boolean;
|
|
64
|
+
//#endregion
|
|
65
|
+
export { SignSlackUserTokenParams, SlackAccessTokenPayload, SlackAccessTokenPayloadSchema, VerifySlackUserTokenResult, isSlackUserToken, signSlackUserToken, verifySlackUserToken };
|
|
@@ -0,0 +1,129 @@
|
|
|
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 };
|
|
@@ -0,0 +1,35 @@
|
|
|
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 };
|
|
@@ -0,0 +1,71 @@
|
|
|
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 };
|
|
@@ -2,9 +2,18 @@ import { Span, Tracer } from "@opentelemetry/api";
|
|
|
2
2
|
|
|
3
3
|
//#region src/utils/tracer-factory.d.ts
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Unwraps nested error `.cause` chains to find the root cause error.
|
|
7
|
+
* Node.js `fetch()` wraps undici errors (e.g. HeadersTimeoutError) into
|
|
8
|
+
* a generic `TypeError: fetch failed` with the real error in `.cause`.
|
|
9
|
+
* This utility traverses the cause chain to surface the original error.
|
|
10
|
+
*/
|
|
11
|
+
declare function unwrapError(error: unknown): Error;
|
|
5
12
|
/**
|
|
6
13
|
* Helper function to handle span errors consistently
|
|
7
|
-
* Records the exception, sets error status, and optionally logs
|
|
14
|
+
* Records the exception, sets error status, and optionally logs.
|
|
15
|
+
* Automatically unwraps `.cause` chains so spans show root cause errors
|
|
16
|
+
* instead of generic wrappers like "fetch failed".
|
|
8
17
|
*/
|
|
9
18
|
declare function setSpanWithError(span: Span, error: Error, logger?: {
|
|
10
19
|
error: (obj: any, msg?: string) => void;
|
|
@@ -15,4 +24,4 @@ declare function setSpanWithError(span: Span, error: Error, logger?: {
|
|
|
15
24
|
*/
|
|
16
25
|
declare function getTracer(serviceName: string, serviceVersion?: string): Tracer;
|
|
17
26
|
//#endregion
|
|
18
|
-
export { getTracer, setSpanWithError };
|
|
27
|
+
export { getTracer, setSpanWithError, unwrapError };
|
|
@@ -32,16 +32,35 @@ const noopTracer = {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
35
|
+
* Unwraps nested error `.cause` chains to find the root cause error.
|
|
36
|
+
* Node.js `fetch()` wraps undici errors (e.g. HeadersTimeoutError) into
|
|
37
|
+
* a generic `TypeError: fetch failed` with the real error in `.cause`.
|
|
38
|
+
* This utility traverses the cause chain to surface the original error.
|
|
39
|
+
*/
|
|
40
|
+
function unwrapError(error) {
|
|
41
|
+
if (!(error instanceof Error)) return new Error(String(error));
|
|
42
|
+
let current = error;
|
|
43
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44
|
+
while (current.cause instanceof Error && !seen.has(current.cause)) {
|
|
45
|
+
seen.add(current);
|
|
46
|
+
current = current.cause;
|
|
47
|
+
}
|
|
48
|
+
return current;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
35
51
|
* Helper function to handle span errors consistently
|
|
36
|
-
* Records the exception, sets error status, and optionally logs
|
|
52
|
+
* Records the exception, sets error status, and optionally logs.
|
|
53
|
+
* Automatically unwraps `.cause` chains so spans show root cause errors
|
|
54
|
+
* instead of generic wrappers like "fetch failed".
|
|
37
55
|
*/
|
|
38
56
|
function setSpanWithError(span, error, logger$1, logMessage) {
|
|
39
|
-
|
|
57
|
+
const rootCause = unwrapError(error);
|
|
58
|
+
span.recordException(rootCause);
|
|
40
59
|
span.setStatus({
|
|
41
60
|
code: SpanStatusCode.ERROR,
|
|
42
|
-
message:
|
|
61
|
+
message: rootCause.message
|
|
43
62
|
});
|
|
44
|
-
if (logger$1 && logMessage) logger$1.error({ error:
|
|
63
|
+
if (logger$1 && logMessage) logger$1.error({ error: rootCause.message }, logMessage);
|
|
45
64
|
}
|
|
46
65
|
/**
|
|
47
66
|
* Get a tracer instance for the specified service
|
|
@@ -57,4 +76,4 @@ function getTracer(serviceName, serviceVersion) {
|
|
|
57
76
|
}
|
|
58
77
|
|
|
59
78
|
//#endregion
|
|
60
|
-
export { getTracer, setSpanWithError };
|
|
79
|
+
export { getTracer, setSpanWithError, unwrapError };
|
package/dist/utils/tracer.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { setSpanWithError } from "./tracer-factory.js";
|
|
1
|
+
import { setSpanWithError, unwrapError } from "./tracer-factory.js";
|
|
2
2
|
import * as _opentelemetry_api0 from "@opentelemetry/api";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/tracer.d.ts
|
|
5
5
|
declare const tracer: _opentelemetry_api0.Tracer;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { setSpanWithError, tracer };
|
|
7
|
+
export { setSpanWithError, tracer, unwrapError };
|
package/dist/utils/tracer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getTracer, setSpanWithError } from "./tracer-factory.js";
|
|
1
|
+
import { getTracer, setSpanWithError, unwrapError } from "./tracer-factory.js";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/tracer.ts
|
|
4
4
|
const tracer = getTracer("agents-core");
|
|
5
5
|
|
|
6
6
|
//#endregion
|
|
7
|
-
export { setSpanWithError, tracer };
|
|
7
|
+
export { setSpanWithError, tracer, unwrapError };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SignatureVerificationConfig, TriggerAuthHeaderInputSchema, TriggerAuthHeaderStoredSchema, TriggerAuthenticationStoredSchema } from "../validation/schemas.js";
|
|
2
|
-
import { Context } from "hono";
|
|
3
2
|
import { z } from "zod";
|
|
3
|
+
import { Context } from "hono";
|
|
4
4
|
|
|
5
5
|
//#region src/utils/trigger-auth.d.ts
|
|
6
6
|
type TriggerAuthHeaderInput = z.infer<typeof TriggerAuthHeaderInputSchema>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from "@hono/zod-openapi";
|
|
2
|
-
import * as
|
|
2
|
+
import * as drizzle_zod0 from "drizzle-zod";
|
|
3
3
|
import { AnySQLiteTable } from "drizzle-orm/sqlite-core";
|
|
4
4
|
|
|
5
5
|
//#region src/validation/drizzle-schema-helpers.d.ts
|
|
6
|
-
declare function createSelectSchemaWithModifiers<T extends AnySQLiteTable>(table: T, overrides?: Partial<Record<keyof T['_']['columns'], (schema: z.ZodTypeAny) => z.ZodTypeAny>>):
|
|
7
|
-
declare function createInsertSchemaWithModifiers<T extends AnySQLiteTable>(table: T, overrides?: Partial<Record<keyof T['_']['columns'], (schema: z.ZodTypeAny) => z.ZodTypeAny>>):
|
|
6
|
+
declare function createSelectSchemaWithModifiers<T extends AnySQLiteTable>(table: T, overrides?: Partial<Record<keyof T['_']['columns'], (schema: z.ZodTypeAny) => z.ZodTypeAny>>): drizzle_zod0.BuildSchema<"select", T["_"]["columns"], drizzle_zod0.BuildRefine<T["_"]["columns"], undefined>, undefined>;
|
|
7
|
+
declare function createInsertSchemaWithModifiers<T extends AnySQLiteTable>(table: T, overrides?: Partial<Record<keyof T['_']['columns'], (schema: z.ZodTypeAny) => z.ZodTypeAny>>): drizzle_zod0.BuildSchema<"insert", T["_"]["columns"], drizzle_zod0.BuildRefine<Pick<T["_"]["columns"], keyof T["$inferInsert"]>, undefined>, undefined>;
|
|
8
8
|
declare const createSelectSchema: typeof createSelectSchemaWithModifiers;
|
|
9
9
|
declare const createInsertSchema: typeof createInsertSchemaWithModifiers;
|
|
10
10
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { JsonSchemaProperty } from "./json-schemas.js";
|
|
2
|
+
import { z } from "@hono/zod-openapi";
|
|
3
|
+
|
|
4
|
+
//#region src/validation/extend-schemas.d.ts
|
|
5
|
+
declare const NameSchema: z.ZodString;
|
|
6
|
+
declare const DescriptionSchema: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
7
|
+
/**
|
|
8
|
+
* Used in z.transform()
|
|
9
|
+
*/
|
|
10
|
+
declare function transformToJson<T extends string>(value: T, ctx: z.RefinementCtx<T>): any;
|
|
11
|
+
declare const DataComponentExtendSchema: {
|
|
12
|
+
name: z.ZodString;
|
|
13
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
14
|
+
props: z.ZodObject<{
|
|
15
|
+
type: z.ZodLiteral<"object">;
|
|
16
|
+
properties: z.ZodRecord<z.ZodString, z.ZodType<JsonSchemaProperty, unknown, z.core.$ZodTypeInternals<JsonSchemaProperty, unknown>>>;
|
|
17
|
+
required: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString>>>;
|
|
18
|
+
additionalProperties: z.ZodOptional<z.ZodBoolean>;
|
|
19
|
+
description: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, z.core.$loose>;
|
|
21
|
+
};
|
|
22
|
+
declare const ArtifactComponentExtendSchema: {
|
|
23
|
+
name: z.ZodString;
|
|
24
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
25
|
+
props: z.ZodNullable<z.ZodObject<{
|
|
26
|
+
type: z.ZodLiteral<"object">;
|
|
27
|
+
properties: z.ZodRecord<z.ZodString, z.ZodType<JsonSchemaProperty, unknown, z.core.$ZodTypeInternals<JsonSchemaProperty, unknown>>>;
|
|
28
|
+
required: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString>>>;
|
|
29
|
+
additionalProperties: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
description: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$loose>>;
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { ArtifactComponentExtendSchema, DataComponentExtendSchema, DescriptionSchema, NameSchema, transformToJson };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { JsonSchemaForLlmSchema } from "./json-schemas.js";
|
|
2
|
+
import { z } from "@hono/zod-openapi";
|
|
3
|
+
|
|
4
|
+
//#region src/validation/extend-schemas.ts
|
|
5
|
+
const NameSchema = z.string().trim().nonempty("Name is required").max(256).openapi("NameSchema");
|
|
6
|
+
const DescriptionSchema = z.string().trim().nullish().openapi("DescriptionSchema");
|
|
7
|
+
/**
|
|
8
|
+
* Used in z.transform()
|
|
9
|
+
*/
|
|
10
|
+
function transformToJson(value, ctx) {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(value);
|
|
13
|
+
} catch {
|
|
14
|
+
ctx.addIssue({
|
|
15
|
+
code: "custom",
|
|
16
|
+
message: "Invalid JSON syntax"
|
|
17
|
+
});
|
|
18
|
+
return z.NEVER;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const DataComponentExtendSchema = {
|
|
22
|
+
name: NameSchema,
|
|
23
|
+
description: DescriptionSchema,
|
|
24
|
+
props: JsonSchemaForLlmSchema
|
|
25
|
+
};
|
|
26
|
+
const ArtifactComponentExtendSchema = {
|
|
27
|
+
name: NameSchema,
|
|
28
|
+
description: DescriptionSchema,
|
|
29
|
+
props: JsonSchemaForLlmSchema.nullable()
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ArtifactComponentExtendSchema, DataComponentExtendSchema, DescriptionSchema, NameSchema, transformToJson };
|