startx 1.0.1 → 1.0.3

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 (147) hide show
  1. package/.dockerignore +4 -0
  2. package/apps/cli/src/commands/index.ts +1 -1
  3. package/apps/cli/src/commands/{common → test}/test.ts +4 -2
  4. package/apps/cli/tsconfig.json +0 -1
  5. package/apps/core-server/Dockerfile +5 -4
  6. package/apps/core-server/package.json +1 -1
  7. package/apps/core-server/tsconfig.json +1 -1
  8. package/apps/queue-worker/package.json +1 -1
  9. package/apps/queue-worker/tsconfig.json +1 -1
  10. package/apps/startx-cli/dist/index.mjs +68 -53
  11. package/apps/startx-cli/src/commands/package.ts +453 -0
  12. package/apps/startx-cli/src/configs/scripts.ts +18 -2
  13. package/apps/startx-cli/src/index.ts +2 -4
  14. package/apps/startx-cli/src/types.ts +2 -4
  15. package/apps/startx-cli/src/utils/inquirer.ts +8 -1
  16. package/apps/web-client/.dockerignore +4 -0
  17. package/apps/web-client/app/app.css +1 -0
  18. package/apps/web-client/app/components.json +23 -0
  19. package/apps/web-client/app/config/auth/auth-state.ts +59 -0
  20. package/apps/web-client/app/config/axios-client.ts +87 -0
  21. package/apps/web-client/app/config/env.ts +5 -0
  22. package/apps/web-client/app/entry.client.tsx +7 -0
  23. package/apps/web-client/app/eslint.config.ts +4 -0
  24. package/apps/web-client/app/root.tsx +77 -0
  25. package/apps/web-client/app/routes/home.tsx +12 -0
  26. package/apps/web-client/app/routes.ts +3 -0
  27. package/apps/web-client/eslint.config.ts +4 -0
  28. package/apps/web-client/package.json +55 -0
  29. package/apps/web-client/react-router.config.ts +7 -0
  30. package/apps/web-client/tsconfig.json +22 -0
  31. package/apps/web-client/vite-env.d.ts +8 -0
  32. package/apps/web-client/vite.config.ts +30 -0
  33. package/biome.json +5 -0
  34. package/configs/eslint-config/eslint.config.ts +1 -0
  35. package/configs/eslint-config/src/configs/base.ts +0 -1
  36. package/configs/eslint-config/src/configs/frontend.ts +1 -1
  37. package/configs/eslint-config/tsconfig.json +1 -1
  38. package/configs/typescript-config/tsconfig.frontend.json +1 -1
  39. package/configs/vitest-config/tsconfig.json +1 -1
  40. package/package.json +1 -1
  41. package/packages/@db/drizzle/tsconfig.json +1 -1
  42. package/packages/@db/sqlite/tsconfig.json +1 -1
  43. package/packages/@repo/env/package.json +1 -2
  44. package/packages/@repo/env/src/utils.ts +17 -11
  45. package/packages/@repo/lib/package.json +3 -1
  46. package/packages/@repo/lib/src/session-module/i-session.ts +108 -0
  47. package/packages/@repo/lib/src/session-module/index.ts +8 -111
  48. package/packages/@repo/lib/src/session-module/redis-session.ts +44 -0
  49. package/packages/@repo/lib/tsconfig.json +0 -1
  50. package/packages/@repo/logger/package.json +0 -1
  51. package/packages/@repo/logger/tsconfig.json +1 -1
  52. package/packages/@repo/mail/tsconfig.json +1 -1
  53. package/packages/@repo/redis/tsconfig.json +1 -1
  54. package/packages/aix/package.json +2 -0
  55. package/packages/aix/src/providers/ai-interface.ts +4 -4
  56. package/packages/aix/src/providers/bedrock/bedrock.ts +261 -0
  57. package/packages/aix/src/providers/default-models.ts +65 -0
  58. package/packages/aix/src/providers/openai/openai.ts +2 -2
  59. package/packages/aix/src/providers/providers.ts +11 -0
  60. package/packages/aix/src/providers/types.ts +1 -1
  61. package/packages/{constants → common}/package.json +4 -2
  62. package/packages/{constants/src/index.ts → common/src/constants.ts} +0 -5
  63. package/packages/common/src/types/users.ts +10 -0
  64. package/packages/{constants → common}/tsconfig.json +0 -3
  65. package/packages/ui/components.json +15 -8
  66. package/packages/ui/package.json +23 -36
  67. package/packages/ui/src/api/axios/i-client.ts +40 -0
  68. package/packages/ui/src/api/index.ts +6 -0
  69. package/packages/ui/src/api/query-provider.tsx +34 -0
  70. package/packages/ui/src/api/use-api/api-builder.ts +139 -0
  71. package/packages/ui/src/api/use-api/api-helpers.ts +165 -0
  72. package/packages/ui/src/api/use-api/api-types.ts +138 -0
  73. package/packages/ui/src/api/use-api/query-factory.ts +66 -0
  74. package/packages/ui/src/api/use-api/react-query/types.ts +64 -0
  75. package/packages/ui/src/api/use-api/react-query/use-api-client.ts +56 -0
  76. package/packages/ui/src/api/use-api/react-query/use-api.ts +297 -0
  77. package/packages/ui/src/components/custom/form-wrapper.tsx +113 -160
  78. package/packages/ui/src/components/custom/grid-component.tsx +4 -4
  79. package/packages/ui/src/components/custom/hover-tool.tsx +1 -1
  80. package/packages/ui/src/components/custom/image-picker.tsx +18 -20
  81. package/packages/ui/src/components/custom/no-content.tsx +6 -16
  82. package/packages/ui/src/components/custom/page-section.tsx +14 -17
  83. package/packages/ui/src/components/custom/simple-popover.tsx +5 -9
  84. package/packages/ui/src/components/custom/theme-provider.tsx +117 -42
  85. package/packages/ui/src/components/custom/typography.tsx +20 -22
  86. package/packages/ui/src/components/extensions/timeline.tsx +100 -0
  87. package/packages/ui/src/components/ui/alert-dialog.tsx +46 -108
  88. package/packages/ui/src/components/ui/avatar.tsx +79 -42
  89. package/packages/ui/src/components/ui/badge.tsx +29 -34
  90. package/packages/ui/src/components/ui/breadcrumb.tsx +65 -81
  91. package/packages/ui/src/components/ui/button.tsx +80 -80
  92. package/packages/ui/src/components/ui/card.tsx +48 -69
  93. package/packages/ui/src/components/ui/carousel.tsx +184 -211
  94. package/packages/ui/src/components/ui/checkbox.tsx +21 -24
  95. package/packages/ui/src/components/ui/command.tsx +121 -102
  96. package/packages/ui/src/components/ui/dialog.tsx +45 -32
  97. package/packages/ui/src/components/ui/dropdown-menu.tsx +45 -33
  98. package/packages/ui/src/components/ui/field.tsx +218 -0
  99. package/packages/ui/src/components/ui/form.tsx +63 -76
  100. package/packages/ui/src/components/ui/input-group.tsx +137 -0
  101. package/packages/ui/src/components/ui/input-otp.tsx +60 -50
  102. package/packages/ui/src/components/ui/input.tsx +16 -15
  103. package/packages/ui/src/components/ui/label.tsx +14 -17
  104. package/packages/ui/src/components/ui/multiple-select.tsx +22 -33
  105. package/packages/ui/src/components/ui/popover.tsx +20 -8
  106. package/packages/ui/src/components/ui/select.tsx +33 -34
  107. package/packages/ui/src/components/ui/separator.tsx +8 -8
  108. package/packages/ui/src/components/ui/sheet.tsx +32 -59
  109. package/packages/ui/src/components/ui/sidebar.tsx +654 -0
  110. package/packages/ui/src/components/ui/skeleton.tsx +2 -8
  111. package/packages/ui/src/components/ui/sonner.tsx +39 -0
  112. package/packages/ui/src/components/ui/spinner.tsx +6 -13
  113. package/packages/ui/src/components/ui/switch.tsx +15 -10
  114. package/packages/ui/src/components/ui/table.tsx +48 -89
  115. package/packages/ui/src/components/ui/tabs.tsx +37 -15
  116. package/packages/ui/src/components/ui/textarea.tsx +13 -13
  117. package/packages/ui/src/components/ui/tooltip.tsx +37 -23
  118. package/packages/ui/src/{components/hooks → hooks}/event/use-click.tsx +6 -10
  119. package/packages/ui/src/hooks/time/use-timer.tsx +51 -0
  120. package/packages/ui/src/hooks/use-media-query.tsx +19 -0
  121. package/packages/ui/src/hooks/use-mobile.tsx +17 -0
  122. package/packages/ui/src/{components/hooks → hooks}/use-update-effect.tsx +2 -2
  123. package/packages/ui/src/lib/utils.ts +113 -0
  124. package/packages/ui/src/styles/globals.css +311 -0
  125. package/packages/ui/src/styles/tailwind.css +89 -0
  126. package/packages/ui/tsconfig.json +7 -9
  127. package/pnpm-workspace.yaml +74 -64
  128. package/packages/ui/postcss.config.mjs +0 -9
  129. package/packages/ui/src/components/extensions/carousel.tsx +0 -392
  130. package/packages/ui/src/components/hooks/time/useTimer.tsx +0 -51
  131. package/packages/ui/src/components/hooks/use-media-query.tsx +0 -19
  132. package/packages/ui/src/components/lib/utils.ts +0 -242
  133. package/packages/ui/src/components/ui/timeline.tsx +0 -118
  134. package/packages/ui/src/components/util/n-formattor.ts +0 -22
  135. package/packages/ui/src/components/util/storage.ts +0 -37
  136. package/packages/ui/src/globals.css +0 -87
  137. package/packages/ui/tailwind.config.ts +0 -94
  138. /package/packages/{constants → common}/eslint.config.ts +0 -0
  139. /package/packages/{constants → common}/src/api.ts +0 -0
  140. /package/packages/{constants → common}/src/time.ts +0 -0
  141. /package/packages/{constants → common}/vitest.config.ts +0 -0
  142. /package/packages/ui/src/{components/hooks/time/useDebounce.tsx → hooks/time/use-debounce.tsx} +0 -0
  143. /package/packages/ui/src/{components/hooks/time/useInterval.tsx → hooks/time/use-interval.tsx} +0 -0
  144. /package/packages/ui/src/{components/hooks/time/useTimeout.tsx → hooks/time/use-timeout.tsx} +0 -0
  145. /package/packages/ui/src/{components/hooks → hooks}/use-persistent-storage.tsx +0 -0
  146. /package/packages/ui/src/{components/hooks → hooks}/use-window-dimension.tsx +0 -0
  147. /package/packages/ui/src/{components/sonner.tsx → sonner.ts} +0 -0
@@ -1,113 +1,10 @@
1
- import { RedisStore } from "@repo/redis";
1
+ import { RedisUserSession } from "./redis-session.js";
2
2
 
3
- import { TokenModule } from "../extra/token-module.js";
4
- export const constants = {
5
- sessionDuration: 60 * 60 * 6,
6
- };
7
-
8
- const accessTokenKey = (key: string) => `access_token:${key}`;
9
- const refreshTokenKey = (key: string) => `refresh_token:${key}`;
10
- const userTokensKey = (userId: string) => `session:${userId}`;
11
- export type SessionUser = {
12
- id: string;
13
- email: string;
14
- fullName: string;
15
- countries: string[];
16
- department: string;
17
- currentScenario?: string;
18
- accessToken: string;
19
- };
20
-
21
- const userRedisStore = new RedisStore<SessionUser>({
22
- namespace: "user-session",
23
- });
24
-
25
- const userRedisTokenStore = new RedisStore<{ accessToken: string; refreshToken: string }>({
26
- namespace: "user-tokens",
27
- });
28
-
29
- export class UserSession {
30
- static async getSessionUser(token: string) {
31
- return await userRedisStore.get(accessTokenKey(token));
32
- }
33
-
34
- static async startSession(payload: Omit<SessionUser, "accessToken">) {
35
- await UserSession.endSession(payload.id);
36
-
37
- const accessToken = TokenModule.signAccessToken({
38
- userID: payload.id,
39
- email: payload.email,
40
- });
41
-
42
- const refreshToken = TokenModule.signRefreshToken({
43
- userID: payload.id,
44
- email: payload.email,
45
- });
46
-
47
- const sessionData: SessionUser = { ...payload, accessToken };
48
-
49
- // store access token -> user
50
- await userRedisStore.set(accessTokenKey(accessToken), sessionData, constants.sessionDuration);
51
-
52
- // store user -> session (optional but useful)
53
- await userRedisStore.set(payload.id, sessionData, constants.sessionDuration);
54
-
55
- // store refresh token -> userId
56
- await userRedisTokenStore.set(
57
- refreshTokenKey(refreshToken),
58
- { accessToken, refreshToken },
59
- constants.sessionDuration
60
- );
61
-
62
- // store user -> tokens
63
- await userRedisTokenStore.set(
64
- userTokensKey(payload.id),
65
- { accessToken, refreshToken },
66
- constants.sessionDuration
67
- );
68
-
69
- return { accessToken, refreshToken };
3
+ export const userSession = (type: "redis" | "pg") => {
4
+ switch (type) {
5
+ case "redis":
6
+ return new RedisUserSession();
7
+ default:
8
+ throw new Error("Unknown session type");
70
9
  }
71
-
72
- static async checkRefreshToken(refreshToken: string) {
73
- const tokens = await userRedisTokenStore.get(refreshTokenKey(refreshToken));
74
- return tokens ?? null;
75
- }
76
-
77
- static async updateAccessToken(payload: Omit<SessionUser, "accessToken">) {
78
- const tokens = await this.getTokens(payload.id);
79
- if (!tokens) return null;
80
-
81
- const accessToken = tokens.accessToken;
82
-
83
- await userRedisStore.set(
84
- accessTokenKey(accessToken),
85
- { ...payload, accessToken },
86
- constants.sessionDuration
87
- );
88
-
89
- return accessToken;
90
- }
91
-
92
- static async getTokens(userId: string) {
93
- return await userRedisTokenStore.get(userTokensKey(userId));
94
- }
95
-
96
- static async logout(accessToken: string) {
97
- const session = await userRedisStore.get(accessTokenKey(accessToken));
98
- if (!session) return null;
99
-
100
- await this.endSession(session.id);
101
- return null;
102
- }
103
-
104
- static async endSession(userId: string) {
105
- const tokens = await this.getTokens(userId);
106
- if (!tokens) return;
107
-
108
- await userRedisTokenStore.del(refreshTokenKey(tokens.refreshToken));
109
- await userRedisStore.del(accessTokenKey(tokens.accessToken));
110
- await userRedisTokenStore.del(userTokensKey(userId));
111
- await userRedisStore.del(userId);
112
- }
113
- }
10
+ };
@@ -0,0 +1,44 @@
1
+ import type { SessionUser } from "@repo/common/types/users";
2
+ import { RedisStore } from "@repo/redis";
3
+ import { IUserSession, type TokenPair } from "./i-session.js";
4
+
5
+ export class RedisUserSession extends IUserSession {
6
+ private userStore: RedisStore<SessionUser>;
7
+ private tokenStore: RedisStore<TokenPair>;
8
+
9
+ constructor() {
10
+ super();
11
+ this.userStore = new RedisStore<SessionUser>({
12
+ namespace: "user-session",
13
+ });
14
+ this.tokenStore = new RedisStore<TokenPair>({
15
+ namespace: "user-tokens",
16
+ });
17
+ }
18
+
19
+ protected async setSessionData(key: string, data: SessionUser, ttl: number): Promise<void> {
20
+ await this.userStore.set(key, data, ttl);
21
+ }
22
+
23
+ protected async getSessionData(key: string): Promise<SessionUser | null> {
24
+ const data = await this.userStore.get(key);
25
+ return data ?? null;
26
+ }
27
+
28
+ protected async deleteSessionData(key: string): Promise<void> {
29
+ await this.userStore.del(key);
30
+ }
31
+
32
+ protected async setTokenData(key: string, data: TokenPair, ttl: number): Promise<void> {
33
+ await this.tokenStore.set(key, data, ttl);
34
+ }
35
+
36
+ protected async getTokenData(key: string): Promise<TokenPair | null> {
37
+ const data = await this.tokenStore.get(key);
38
+ return data ?? null;
39
+ }
40
+
41
+ protected async deleteTokenData(key: string): Promise<void> {
42
+ await this.tokenStore.del(key);
43
+ }
44
+ }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "extends": "typescript-config/tsconfig.node.json",
3
3
  "compilerOptions": {
4
- "baseUrl": "./src",
5
4
  "jsx": "react"
6
5
  },
7
6
  "include": ["src/**/*.ts"]
@@ -23,7 +23,6 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "winston": "catalog:",
26
- "dotenv": "catalog:",
27
26
  "@repo/env": "workspace:*"
28
27
  },
29
28
  "startx": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "extends": "typescript-config/tsconfig.node.json",
3
3
  "compilerOptions": {
4
- "baseUrl": "./src"
4
+ // "baseUrl": "./src"
5
5
  },
6
6
  "include": ["src/**/*.ts"]
7
7
  }
@@ -3,7 +3,7 @@
3
3
  "compilerOptions": {
4
4
  "rootDir": ".",
5
5
  "types": ["node", "react"],
6
- "baseUrl": "src",
6
+ // "baseUrl": "src",
7
7
  "jsx": "react",
8
8
  "tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
9
9
  "experimentalDecorators": true,
@@ -3,7 +3,7 @@
3
3
  "compilerOptions": {
4
4
  "rootDir": ".",
5
5
  "types": ["node"],
6
- "baseUrl": "src",
6
+ // "baseUrl": "src",
7
7
  "tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
8
8
  "experimentalDecorators": true,
9
9
  "emitDecoratorMetadata": true
@@ -21,6 +21,8 @@
21
21
  "vitest-config": "workspace:*"
22
22
  },
23
23
  "dependencies": {
24
+ "@aws-sdk/client-bedrock": "^3.1047.0",
25
+ "@aws-sdk/client-bedrock-runtime": "^3.1047.0",
24
26
  "@repo/env": "workspace:*",
25
27
  "@repo/lib": "workspace:*",
26
28
  "@repo/logger": "workspace:*",
@@ -26,9 +26,9 @@ export interface AiInterfaceConstructor<T extends AiProvider = AiProvider> {
26
26
  model: (typeof DefaultAiModels)[T][number]["id"];
27
27
  conversations: AiChatMessage[];
28
28
  credentials: {
29
- apiKey: string;
29
+ apiKey?: string;
30
30
  baseUrl?: string;
31
- };
31
+ } & Record<string, string | undefined>;
32
32
  tokens?: Partial<Record<"maxLimit" | "current" | "total", { input: number; output: number }>> & {
33
33
  minTokenToGenerateSchemaOnToolCall?: number;
34
34
  };
@@ -53,10 +53,10 @@ export abstract class AiInterface<AI, P extends AiProvider> {
53
53
  }
54
54
  abstract ai: AI;
55
55
  protected abstract handleAi(): Promise<void>;
56
- abstract listModels(): Promise<{
56
+ abstract listModels(): Promise<Array<{
57
57
  provider: string;
58
58
  name: string;
59
- }>;
59
+ }>>;
60
60
  protected model: (typeof DefaultAiModels)[P][number]["id"];
61
61
  protected credentials: AiInterfaceConstructor["credentials"];
62
62
  private iInternal: TInternal;
@@ -0,0 +1,261 @@
1
+ import { BedrockClient as AwsBedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";
2
+ import {
3
+ BedrockRuntimeClient,
4
+ ConverseCommand,
5
+ type Tool,
6
+ type Message,
7
+ type SystemContentBlock,
8
+ type ToolUseBlock,
9
+ } from "@aws-sdk/client-bedrock-runtime";
10
+
11
+ import { AiInterface, type AiInterfaceConstructor } from "../ai-interface.js";
12
+
13
+ type BedrockCredentials = {
14
+ accessKeyId: string;
15
+ secretAccessKey: string;
16
+ sessionToken?: string;
17
+ region: string;
18
+ };
19
+
20
+ export class BedrockClient extends AiInterface<BedrockRuntimeClient, "bedrock"> {
21
+ ai: BedrockRuntimeClient;
22
+ private controlPlane: AwsBedrockClient;
23
+
24
+ constructor(
25
+ props: AiInterfaceConstructor & {
26
+ credentials: BedrockCredentials;
27
+ }
28
+ ) {
29
+ super(props);
30
+
31
+ const awsConfig = {
32
+ region: props.credentials.region,
33
+ credentials: {
34
+ accessKeyId: props.credentials.accessKeyId,
35
+ secretAccessKey: props.credentials.secretAccessKey,
36
+ sessionToken: props.credentials.sessionToken,
37
+ },
38
+ };
39
+
40
+ this.ai = new BedrockRuntimeClient(awsConfig);
41
+
42
+ this.controlPlane = new AwsBedrockClient(awsConfig);
43
+ }
44
+
45
+ async listModels() {
46
+ const models = await this.controlPlane.send(new ListFoundationModelsCommand({}));
47
+ return (
48
+ models.modelSummaries?.map(e => ({
49
+ provider: e.providerName!,
50
+ name: e.modelName!,
51
+ })) ?? []
52
+ );
53
+ }
54
+
55
+ private mapMessages(): { messages: Message[]; system: SystemContentBlock[] } {
56
+ const messages: Message[] = [];
57
+ const system: SystemContentBlock[] = [];
58
+
59
+ for (const msg of this.chats.getMessages()) {
60
+ if (msg.role === "system") {
61
+ system.push({ text: msg.content });
62
+ continue;
63
+ }
64
+
65
+ if (msg.role === "tool") {
66
+ messages.push({
67
+ role: "user",
68
+ content: [
69
+ {
70
+ toolResult: {
71
+ toolUseId: msg.tool_call_id,
72
+ content: [{ text: msg.content }],
73
+ },
74
+ },
75
+ ],
76
+ });
77
+ continue;
78
+ }
79
+
80
+ const contentBlocks: Message["content"] = [];
81
+
82
+ if (msg.content) {
83
+ contentBlocks.push({ text: msg.content });
84
+ }
85
+
86
+ if (msg.role === "assistant" && "tool_calls" in msg) {
87
+ msg.tool_calls.forEach(tc => {
88
+ if (tc.type === "function") {
89
+ const func = tc as unknown as {
90
+ function: {
91
+ name: string;
92
+ arguments: string;
93
+ };
94
+ };
95
+ contentBlocks.push({
96
+ toolUse: {
97
+ toolUseId: tc.id,
98
+ name: func.function.name,
99
+ input: JSON.parse(func.function.arguments) as ToolUseBlock["input"],
100
+ },
101
+ });
102
+ }
103
+ });
104
+ }
105
+
106
+ messages.push({
107
+ role: msg.role === "assistant" ? "assistant" : "user",
108
+ content: contentBlocks,
109
+ });
110
+ }
111
+
112
+ return { messages, system };
113
+ }
114
+
115
+ private mapTools(): Tool[] {
116
+ return this.tools.getActiveTools().map(tool => ({
117
+ toolSpec: {
118
+ name: tool.name,
119
+ description: tool.description,
120
+ inputSchema: {
121
+ json: tool.input_schema.toJSONSchema(),
122
+ },
123
+ },
124
+ })) as Tool[];
125
+ }
126
+
127
+ async handleAi() {
128
+ const getCompletion = async () => {
129
+ try {
130
+ const tools = this.mapTools();
131
+ const { messages, system } = this.mapMessages();
132
+
133
+ const response = await this.ai.send(
134
+ new ConverseCommand({
135
+ modelId: this.model,
136
+ messages,
137
+ system: system.length ? system : undefined,
138
+ inferenceConfig: {
139
+ temperature: this.preferences.temperature,
140
+ maxTokens: this.preferences.maxCompletionTokens,
141
+ },
142
+ ...(tools.length
143
+ ? {
144
+ toolConfig: {
145
+ tools,
146
+ toolChoice: this.preferences.toolOnly ? { any: {} } : { auto: {} },
147
+ },
148
+ }
149
+ : {}),
150
+ })
151
+ );
152
+
153
+ if (response.usage) {
154
+ this.event.emit("token", {
155
+ input: response.usage.inputTokens ?? 0,
156
+ output: response.usage.outputTokens ?? 0,
157
+ });
158
+ }
159
+
160
+ return response;
161
+ } catch (error) {
162
+ const err = error as Error;
163
+
164
+ this.event.emit("log", {
165
+ type: "error",
166
+ message: err.message,
167
+ meta: err.cause as Record<string, unknown>,
168
+ stack: err.stack,
169
+ });
170
+
171
+ throw error;
172
+ }
173
+ };
174
+
175
+ let response = await getCompletion();
176
+
177
+ while (true) {
178
+ const output = response.output?.message;
179
+
180
+ if (!output) {
181
+ this.event.emit("log", {
182
+ type: "warn",
183
+ message: `⚠️ No output returned: ${JSON.stringify(response, null, 2)}`,
184
+ });
185
+ return;
186
+ }
187
+
188
+ let assistantText = "";
189
+ const toolCalls: Array<{
190
+ id: string;
191
+ type: "function";
192
+ function: {
193
+ name: string;
194
+ arguments: string;
195
+ };
196
+ }> = [];
197
+
198
+ for (const part of output.content ?? []) {
199
+ if ("text" in part && part.text) {
200
+ assistantText += part.text;
201
+ }
202
+
203
+ if ("toolUse" in part && part.toolUse) {
204
+ toolCalls.push({
205
+ id: part.toolUse.toolUseId!,
206
+ type: "function",
207
+ function: {
208
+ name: part.toolUse.name!,
209
+ arguments: JSON.stringify(part.toolUse.input ?? {}),
210
+ },
211
+ });
212
+ }
213
+ }
214
+
215
+ this.chats.addMessage({
216
+ role: "assistant",
217
+ content: assistantText,
218
+ tool_calls: toolCalls.length ? toolCalls : undefined,
219
+ timestamp: new Date(),
220
+ });
221
+
222
+ if (assistantText && toolCalls.length === 0) {
223
+ return;
224
+ }
225
+
226
+ if (!toolCalls.length) {
227
+ return;
228
+ }
229
+
230
+ for (const toolCall of toolCalls) {
231
+ let toolArgs: object = {};
232
+
233
+ try {
234
+ toolArgs = JSON.parse(toolCall.function.arguments) as Record<string, unknown>;
235
+ } catch (err) {
236
+ this.event.emit("log", {
237
+ type: "error",
238
+ message: `Tool: ${toolCall.function.name}⚠️ Failed to parse tool arguments: ${toolCall.function.arguments}`,
239
+ meta: { err },
240
+ });
241
+ continue;
242
+ }
243
+
244
+ const result = await this.callTool({
245
+ args: toolArgs as Record<string, unknown>,
246
+ name: toolCall.function.name,
247
+ toolCallId: toolCall.id,
248
+ });
249
+
250
+ if (result.isCompleted) {
251
+ return;
252
+ }
253
+ if (result.isError) {
254
+ return;
255
+ }
256
+ }
257
+
258
+ response = await getCompletion();
259
+ }
260
+ }
261
+ }
@@ -458,6 +458,71 @@ export const DefaultAiModels = {
458
458
  type: "text-completion",
459
459
  },
460
460
  ],
461
+ bedrock: [
462
+ {
463
+ id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
464
+ owner: "Anthropic",
465
+ contextWindowToken: 200000,
466
+ maxCompletionToken: 16384,
467
+ type: "text-completion",
468
+ },
469
+ {
470
+ id: "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
471
+ owner: "Anthropic",
472
+ contextWindowToken: 200000,
473
+ maxCompletionToken: 16384,
474
+ type: "text-completion",
475
+ },
476
+ {
477
+ id: "us.anthropic.claude-opus-4-6-v1",
478
+ owner: "Anthropic",
479
+ contextWindowToken: 200000,
480
+ maxCompletionToken: 16384,
481
+ type: "text-completion",
482
+ },
483
+ {
484
+ id: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
485
+ owner: "Anthropic",
486
+ contextWindowToken: 200000,
487
+ maxCompletionToken: 16384,
488
+ type: "text-completion",
489
+ },
490
+ {
491
+ id: "amazon.nova-pro-v1:0",
492
+ owner: "Amazon",
493
+ contextWindowToken: 300000,
494
+ maxCompletionToken: 5120,
495
+ type: "text-completion",
496
+ },
497
+ {
498
+ id: "amazon.nova-lite-v1:0",
499
+ owner: "Amazon",
500
+ contextWindowToken: 300000,
501
+ maxCompletionToken: 5120,
502
+ type: "text-completion",
503
+ },
504
+ {
505
+ id: "openai.gpt-oss-120b-1:0",
506
+ owner: "OpenAI",
507
+ contextWindowToken: 128000,
508
+ maxCompletionToken: 16384,
509
+ type: "text-completion",
510
+ },
511
+ {
512
+ id: "openai.gpt-oss-20b-1:0",
513
+ owner: "OpenAI",
514
+ contextWindowToken: 128000,
515
+ maxCompletionToken: 16384,
516
+ type: "text-completion",
517
+ },
518
+ // {
519
+ // id: "cohere.embed-english-v3",
520
+ // owner: "Cohere",
521
+ // contextWindowToken: 2048,
522
+ // maxCompletionToken: 0,
523
+ // type: "embedding",
524
+ // },
525
+ ],
461
526
  } as const satisfies Record<
462
527
  AiProvider,
463
528
  ReadonlyArray<{
@@ -7,8 +7,8 @@ export class OpenAIClient extends AiInterface<OpenAI, "openAi"> {
7
7
  this.ai = new OpenAI({ apiKey: props.credentials.apiKey, baseURL: props.credentials.baseUrl });
8
8
  }
9
9
  ai: OpenAI;
10
- async listModels(): Promise<any> {
11
- return await this.ai.models.list();
10
+ async listModels() {
11
+ return (await this.ai.models.list()).data.map(e => ({ name: e.id, provider: "openAi" }));
12
12
  }
13
13
  async handleAi() {
14
14
  const getCompletion = async (retries = 1): Promise<OpenAI.Chat.ChatCompletion> => {
@@ -1,4 +1,5 @@
1
1
  import type { AiInterfaceConstructor } from "./ai-interface.js";
2
+ import { BedrockClient } from "./bedrock/bedrock.js";
2
3
  import { OpenAIClient } from "./openai/openai.js";
3
4
  import type { AiProvider } from "./types.js";
4
5
  export function aiProvider<T extends AiProvider>(type: T) {
@@ -32,6 +33,16 @@ export function aiProvider<T extends AiProvider>(type: T) {
32
33
  });
33
34
  case "cloudflare":
34
35
  return new OpenAIClient(props);
36
+ case "bedrock":
37
+ return new BedrockClient({
38
+ ...props,
39
+ credentials: {
40
+ accessKeyId: props.credentials.accessKeyId!,
41
+ secretAccessKey: props.credentials.secretAccessKey!,
42
+ sessionToken: props.credentials.sessionToken,
43
+ region: props.credentials.region!,
44
+ },
45
+ });
35
46
  default:
36
47
  throw new Error("Provider not implemented");
37
48
  }
@@ -1,4 +1,4 @@
1
- export type AiProvider = "groq" | "openAi" | "cloudflare" | "gemini" | "anthropic" | "cerebras";
1
+ export type AiProvider = "groq" | "openAi" | "cloudflare" | "gemini" | "anthropic" | "cerebras" | "bedrock";
2
2
  export type AiProviderModelType = "text-completion" | "image-generation" | "audio-generation";
3
3
 
4
4
  export type AiChatRole = "user" | "system" | "assistant";
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "constants",
2
+ "name": "@repo/common",
3
3
  "version": "0.12.0",
4
4
  "type": "module",
5
5
 
@@ -13,7 +13,9 @@
13
13
  "lint:fix": "eslint . --fix",
14
14
  "watch": "tsc -p tsconfig.build.json --watch"
15
15
  },
16
- "exports": "./src/index.ts",
16
+ "exports": {
17
+ "./*": "./src/*.ts"
18
+ },
17
19
  "devDependencies": {
18
20
  "typescript-config": "workspace:*",
19
21
  "eslint-config": "workspace:*",
@@ -1,8 +1,3 @@
1
- export * from "./api.js";
2
-
3
- export { Time } from "./time.js";
4
-
5
1
  export const MIN_PASSWORD_CHAR_LENGTH = 8;
6
-
7
2
  export const MAX_PASSWORD_CHAR_LENGTH = 64;
8
3
  export const ping = "pong";
@@ -0,0 +1,10 @@
1
+ export type SessionUserRole = "user" | "admin";
2
+
3
+ export type SessionUser = {
4
+ id: string;
5
+ email: string;
6
+ fullName: string;
7
+ role: SessionUserRole;
8
+ currentProfile: SessionUserRole;
9
+ accessToken: string;
10
+ };
@@ -1,7 +1,4 @@
1
1
  {
2
2
  "extends": "typescript-config/tsconfig.common.json",
3
- "compilerOptions": {
4
- "baseUrl": "./src"
5
- },
6
3
  "include": ["src/**/*.ts"]
7
4
  }