@coursebuilder/server 0.1.0-canary.0.0c9beb2ae
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/LICENSE +21 -0
- package/dist/actions/checkout.d.ts +6 -0
- package/dist/actions/checkout.js +9 -0
- package/dist/actions/checkout.js.map +1 -0
- package/dist/actions/claimed.d.ts +6 -0
- package/dist/actions/claimed.js +8 -0
- package/dist/actions/claimed.js.map +1 -0
- package/dist/actions/create-magic-link.d.ts +6 -0
- package/dist/actions/create-magic-link.js +9 -0
- package/dist/actions/create-magic-link.js.map +1 -0
- package/dist/actions/index.d.ts +11 -0
- package/dist/actions/index.js +18 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/prices-coupon-for-code.d.ts +6 -0
- package/dist/actions/prices-coupon-for-code.js +63 -0
- package/dist/actions/prices-coupon-for-code.js.map +1 -0
- package/dist/actions/prices-formatted.d.ts +6 -0
- package/dist/actions/prices-formatted.js +8 -0
- package/dist/actions/prices-formatted.js.map +1 -0
- package/dist/actions/process-refund.d.ts +1 -0
- package/dist/actions/process-refund.js +8 -0
- package/dist/actions/process-refund.js.map +1 -0
- package/dist/actions/redeem.d.ts +1 -0
- package/dist/actions/redeem.js +8 -0
- package/dist/actions/redeem.js.map +1 -0
- package/dist/actions/transfer-purchase.d.ts +1 -0
- package/dist/actions/transfer-purchase.js +8 -0
- package/dist/actions/transfer-purchase.js.map +1 -0
- package/dist/actions/user-lookup.d.ts +6 -0
- package/dist/actions/user-lookup.js +9 -0
- package/dist/actions/user-lookup.js.map +1 -0
- package/dist/adapter-BtDS6LDw.d.ts +9 -0
- package/dist/chunk-22AMOZYZ.js +67 -0
- package/dist/chunk-22AMOZYZ.js.map +1 -0
- package/dist/chunk-4EQQSW57.js +32 -0
- package/dist/chunk-4EQQSW57.js.map +1 -0
- package/dist/chunk-4LZZLN6T.js +52 -0
- package/dist/chunk-4LZZLN6T.js.map +1 -0
- package/dist/chunk-4QQA3TC2.js +29 -0
- package/dist/chunk-4QQA3TC2.js.map +1 -0
- package/dist/chunk-4TSEPUSC.js +160 -0
- package/dist/chunk-4TSEPUSC.js.map +1 -0
- package/dist/chunk-5O4UO4IR.js +93 -0
- package/dist/chunk-5O4UO4IR.js.map +1 -0
- package/dist/chunk-7FCQOLKL.js +26 -0
- package/dist/chunk-7FCQOLKL.js.map +1 -0
- package/dist/chunk-AZLUMIIF.js +8 -0
- package/dist/chunk-AZLUMIIF.js.map +1 -0
- package/dist/chunk-E6HV6TNI.js +38 -0
- package/dist/chunk-E6HV6TNI.js.map +1 -0
- package/dist/chunk-ECNJPNPU.js +54 -0
- package/dist/chunk-ECNJPNPU.js.map +1 -0
- package/dist/chunk-F3KUYN5I.js +111 -0
- package/dist/chunk-F3KUYN5I.js.map +1 -0
- package/dist/chunk-G63YAJF2.js +107 -0
- package/dist/chunk-G63YAJF2.js.map +1 -0
- package/dist/chunk-JFR7XO72.js +7 -0
- package/dist/chunk-JFR7XO72.js.map +1 -0
- package/dist/chunk-KNC7QVGZ.js +26 -0
- package/dist/chunk-KNC7QVGZ.js.map +1 -0
- package/dist/chunk-ODSSRMD2.js +270 -0
- package/dist/chunk-ODSSRMD2.js.map +1 -0
- package/dist/chunk-VEKYIR7I.js +26 -0
- package/dist/chunk-VEKYIR7I.js.map +1 -0
- package/dist/chunk-W7YAT4NR.js +12 -0
- package/dist/chunk-W7YAT4NR.js.map +1 -0
- package/dist/chunk-WGAPYIUP.js +56 -0
- package/dist/chunk-WGAPYIUP.js.map +1 -0
- package/dist/chunk-WYNH2AWD.js +7 -0
- package/dist/chunk-WYNH2AWD.js.map +1 -0
- package/dist/chunk-Y5X5J55Z.js +384 -0
- package/dist/chunk-Y5X5J55Z.js.map +1 -0
- package/dist/chunk-YFLGJIMA.js +216 -0
- package/dist/chunk-YFLGJIMA.js.map +1 -0
- package/dist/chunk-ZFZNN4E5.js +7 -0
- package/dist/chunk-ZFZNN4E5.js.map +1 -0
- package/dist/create-inngest-middleware.d.ts +635 -0
- package/dist/create-inngest-middleware.js +12 -0
- package/dist/create-inngest-middleware.js.map +1 -0
- package/dist/http-router.d.ts +20 -0
- package/dist/http-router.js +24 -0
- package/dist/http-router.js.map +1 -0
- package/dist/http.d.ts +38 -0
- package/dist/http.js +32 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +365 -0
- package/dist/index.js.map +1 -0
- package/dist/magic-string.es-ENO43NON.js +1389 -0
- package/dist/magic-string.es-ENO43NON.js.map +1 -0
- package/dist/runtime/actions.d.ts +5 -0
- package/dist/runtime/actions.js +8 -0
- package/dist/runtime/actions.js.map +1 -0
- package/dist/runtime/assert.d.ts +15 -0
- package/dist/runtime/assert.js +8 -0
- package/dist/runtime/assert.js.map +1 -0
- package/dist/runtime/cookie.d.ts +8 -0
- package/dist/runtime/cookie.js +8 -0
- package/dist/runtime/cookie.js.map +1 -0
- package/dist/runtime/env.d.ts +9 -0
- package/dist/runtime/env.js +11 -0
- package/dist/runtime/env.js.map +1 -0
- package/dist/runtime/env.test.d.ts +2 -0
- package/dist/runtime/env.test.js +14956 -0
- package/dist/runtime/env.test.js.map +1 -0
- package/dist/runtime/init.d.ts +26 -0
- package/dist/runtime/init.js +14 -0
- package/dist/runtime/init.js.map +1 -0
- package/dist/runtime/logger.d.ts +4 -0
- package/dist/runtime/logger.js +10 -0
- package/dist/runtime/logger.js.map +1 -0
- package/dist/runtime/merge.d.ts +4 -0
- package/dist/runtime/merge.js +8 -0
- package/dist/runtime/merge.js.map +1 -0
- package/dist/runtime/providers.d.ts +21 -0
- package/dist/runtime/providers.js +9 -0
- package/dist/runtime/providers.js.map +1 -0
- package/dist/runtime/web.d.ts +29 -0
- package/dist/runtime/web.js +16 -0
- package/dist/runtime/web.js.map +1 -0
- package/package.json +65 -0
- package/src/actions/actions.test.ts +232 -0
- package/src/actions/checkout.ts +160 -0
- package/src/actions/claimed.ts +40 -0
- package/src/actions/create-magic-link.ts +78 -0
- package/src/actions/index.ts +401 -0
- package/src/actions/prices-coupon-for-code.ts +91 -0
- package/src/actions/prices-formatted.ts +313 -0
- package/src/actions/process-refund.ts +2 -0
- package/src/actions/redeem.ts +2 -0
- package/src/actions/transfer-purchase.ts +2 -0
- package/src/actions/user-lookup.ts +37 -0
- package/src/adapter.ts +28 -0
- package/src/create-inngest-middleware.ts +157 -0
- package/src/http-actions.ts +29 -0
- package/src/http-router.ts +79 -0
- package/src/http.test.ts +46 -0
- package/src/http.ts +83 -0
- package/src/index.test.ts +21 -0
- package/src/index.ts +44 -0
- package/src/mock-adapter.ts +398 -0
- package/src/mock-payment-provider.ts +56 -0
- package/src/resource-chat.ts +371 -0
- package/src/runtime/actions.ts +25 -0
- package/src/runtime/assert.ts +55 -0
- package/src/runtime/cookie.ts +12 -0
- package/src/runtime/env.test.ts +49 -0
- package/src/runtime/env.ts +63 -0
- package/src/runtime/init.ts +112 -0
- package/src/runtime/logger.ts +6 -0
- package/src/runtime/merge.ts +25 -0
- package/src/runtime/providers.ts +38 -0
- package/src/runtime/web.ts +199 -0
- package/src/streaming-chat-prompt-executor.ts +43 -0
- package/src/type-contracts.test.ts +167 -0
- package/src/web-body-parse.test.ts +55 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
coreInngest,
|
|
3
|
+
createInngestMiddleware,
|
|
4
|
+
defineCourseBuilderFunctions
|
|
5
|
+
} from "./chunk-Y5X5J55Z.js";
|
|
6
|
+
import "./chunk-WGAPYIUP.js";
|
|
7
|
+
export {
|
|
8
|
+
coreInngest,
|
|
9
|
+
createInngestMiddleware,
|
|
10
|
+
defineCourseBuilderFunctions
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=create-inngest-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RequestInternal, ResponseInternal } from '@coursebuilder/core/types';
|
|
2
|
+
import { CourseBuilderConfig } from './http.js';
|
|
3
|
+
import 'inngest';
|
|
4
|
+
import './adapter-BtDS6LDw.js';
|
|
5
|
+
import '@coursebuilder/core/auth';
|
|
6
|
+
import '@coursebuilder/core/ports';
|
|
7
|
+
import '@coursebuilder/core/providers';
|
|
8
|
+
import '@coursebuilder/core/schemas';
|
|
9
|
+
import '@coursebuilder/utils/logger';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Route an internal Course Builder request to its runtime action.
|
|
13
|
+
*
|
|
14
|
+
* @param request - Parsed internal request.
|
|
15
|
+
* @param courseBuilderOptions - Server runtime configuration.
|
|
16
|
+
* @returns The internal response emitted by the selected action.
|
|
17
|
+
*/
|
|
18
|
+
declare function CourseBuilderInternal(request: RequestInternal, courseBuilderOptions: CourseBuilderConfig): Promise<ResponseInternal>;
|
|
19
|
+
|
|
20
|
+
export { CourseBuilderInternal };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CourseBuilderInternal
|
|
3
|
+
} from "./chunk-G63YAJF2.js";
|
|
4
|
+
import "./chunk-5O4UO4IR.js";
|
|
5
|
+
import "./chunk-W7YAT4NR.js";
|
|
6
|
+
import "./chunk-4QQA3TC2.js";
|
|
7
|
+
import "./chunk-KNC7QVGZ.js";
|
|
8
|
+
import "./chunk-4TSEPUSC.js";
|
|
9
|
+
import "./chunk-YFLGJIMA.js";
|
|
10
|
+
import "./chunk-JFR7XO72.js";
|
|
11
|
+
import "./chunk-WYNH2AWD.js";
|
|
12
|
+
import "./chunk-ZFZNN4E5.js";
|
|
13
|
+
import "./chunk-4EQQSW57.js";
|
|
14
|
+
import "./chunk-VEKYIR7I.js";
|
|
15
|
+
import "./chunk-F3KUYN5I.js";
|
|
16
|
+
import "./chunk-7FCQOLKL.js";
|
|
17
|
+
import "./chunk-22AMOZYZ.js";
|
|
18
|
+
import "./chunk-AZLUMIIF.js";
|
|
19
|
+
import "./chunk-ODSSRMD2.js";
|
|
20
|
+
import "./chunk-WGAPYIUP.js";
|
|
21
|
+
export {
|
|
22
|
+
CourseBuilderInternal
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=http-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Inngest } from 'inngest';
|
|
2
|
+
import { S as ServerAdapter } from './adapter-BtDS6LDw.js';
|
|
3
|
+
import { CourseBuilderAuthConfig } from '@coursebuilder/core/auth';
|
|
4
|
+
import { Provider } from '@coursebuilder/core/providers';
|
|
5
|
+
import { User } from '@coursebuilder/core/schemas';
|
|
6
|
+
import { CourseBuilderAction, CallbacksOptions, CookiesOptions } from '@coursebuilder/core/types';
|
|
7
|
+
import { LoggerInstance } from '@coursebuilder/utils/logger';
|
|
8
|
+
import '@coursebuilder/core/ports';
|
|
9
|
+
|
|
10
|
+
/** Set default env variables on the config object */
|
|
11
|
+
declare function setEnvDefaults(envObject: any, config: CourseBuilderConfig): void;
|
|
12
|
+
declare function createActionURL(action: CourseBuilderAction, protocol: string, headers: Headers, envObject: any, basePath?: string): URL;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handle a Course Builder HTTP request.
|
|
16
|
+
*
|
|
17
|
+
* @param request - Web-standard request to route.
|
|
18
|
+
* @param config - Course Builder server runtime configuration.
|
|
19
|
+
* @returns The web-standard response produced by the selected action.
|
|
20
|
+
*/
|
|
21
|
+
declare function CourseBuilder(request: Request, config: CourseBuilderConfig): Promise<Response>;
|
|
22
|
+
/** Runtime configuration consumed by the server-owned HTTP entry point. */
|
|
23
|
+
interface CourseBuilderConfig {
|
|
24
|
+
callbacks?: Partial<CallbacksOptions>;
|
|
25
|
+
adapter?: ServerAdapter;
|
|
26
|
+
providers: Provider[];
|
|
27
|
+
debug?: boolean;
|
|
28
|
+
basePath?: string;
|
|
29
|
+
logger?: LoggerInstance;
|
|
30
|
+
cookies?: Partial<CookiesOptions>;
|
|
31
|
+
useSecureCookies?: boolean;
|
|
32
|
+
inngest?: Inngest;
|
|
33
|
+
getCurrentUser?: () => Promise<User | null>;
|
|
34
|
+
authConfig: CourseBuilderAuthConfig;
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { CourseBuilder, type CourseBuilderConfig, createActionURL, setEnvDefaults };
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CourseBuilder
|
|
3
|
+
} from "./chunk-ECNJPNPU.js";
|
|
4
|
+
import {
|
|
5
|
+
createActionURL,
|
|
6
|
+
setEnvDefaults
|
|
7
|
+
} from "./chunk-4LZZLN6T.js";
|
|
8
|
+
import "./chunk-E6HV6TNI.js";
|
|
9
|
+
import "./chunk-G63YAJF2.js";
|
|
10
|
+
import "./chunk-5O4UO4IR.js";
|
|
11
|
+
import "./chunk-W7YAT4NR.js";
|
|
12
|
+
import "./chunk-4QQA3TC2.js";
|
|
13
|
+
import "./chunk-KNC7QVGZ.js";
|
|
14
|
+
import "./chunk-4TSEPUSC.js";
|
|
15
|
+
import "./chunk-YFLGJIMA.js";
|
|
16
|
+
import "./chunk-JFR7XO72.js";
|
|
17
|
+
import "./chunk-WYNH2AWD.js";
|
|
18
|
+
import "./chunk-ZFZNN4E5.js";
|
|
19
|
+
import "./chunk-4EQQSW57.js";
|
|
20
|
+
import "./chunk-VEKYIR7I.js";
|
|
21
|
+
import "./chunk-F3KUYN5I.js";
|
|
22
|
+
import "./chunk-7FCQOLKL.js";
|
|
23
|
+
import "./chunk-22AMOZYZ.js";
|
|
24
|
+
import "./chunk-AZLUMIIF.js";
|
|
25
|
+
import "./chunk-ODSSRMD2.js";
|
|
26
|
+
import "./chunk-WGAPYIUP.js";
|
|
27
|
+
export {
|
|
28
|
+
CourseBuilder,
|
|
29
|
+
createActionURL,
|
|
30
|
+
setEnvDefaults
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as inngest from 'inngest';
|
|
2
|
+
import * as _coursebuilder_core_events from '@coursebuilder/core/events';
|
|
3
|
+
export { PURCHASE_BENEFITS_ATTACHED_EVENT, TEAM_SEAT_REDEMPTION_CREATED_EVENT } from '@coursebuilder/core/events/commerce';
|
|
4
|
+
export { CourseBuilder, CourseBuilderConfig, createActionURL, setEnvDefaults } from './http.js';
|
|
5
|
+
export { CourseBuilderInternal } from './http-router.js';
|
|
6
|
+
export { CoreInngest, CoreInngestContext, CoreInngestFunctionInput, CoreInngestHandler, CoreInngestTrigger, CourseBuilderFunctionDefinition, CourseBuilderHandlerInput, coreInngest, createInngestMiddleware, defineCourseBuilderFunctions } from './create-inngest-middleware.js';
|
|
7
|
+
import './adapter-BtDS6LDw.js';
|
|
8
|
+
import '@coursebuilder/core/auth';
|
|
9
|
+
import '@coursebuilder/core/ports';
|
|
10
|
+
import '@coursebuilder/core/providers';
|
|
11
|
+
import '@coursebuilder/core/schemas';
|
|
12
|
+
import '@coursebuilder/core/types';
|
|
13
|
+
import '@coursebuilder/utils/logger';
|
|
14
|
+
import 'ai';
|
|
15
|
+
import '@coursebuilder/core/providers/openai';
|
|
16
|
+
import '@coursebuilder/core/providers/partykit';
|
|
17
|
+
import '@coursebuilder/core/providers/slack';
|
|
18
|
+
|
|
19
|
+
/** @deprecated Import this provider-neutral event map from `@coursebuilder/core/events`. */
|
|
20
|
+
type CourseBuilderCoreEvents = _coursebuilder_core_events.CourseBuilderCoreEvents;
|
|
21
|
+
|
|
22
|
+
declare const courseBuilderCoreFunctions: {
|
|
23
|
+
config: {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
trigger: {
|
|
28
|
+
event: "resource/chat-request-event" | keyof _coursebuilder_core_events.CommerceEvents | keyof _coursebuilder_core_events.PurchaseTransferEvents | keyof _coursebuilder_core_events.StripeEvents | keyof _coursebuilder_core_events.VideoEvents;
|
|
29
|
+
if?: string | undefined;
|
|
30
|
+
} & Partial<Record<"cron", never>>;
|
|
31
|
+
handler: inngest.Handler.Any;
|
|
32
|
+
}[];
|
|
33
|
+
|
|
34
|
+
export { type CourseBuilderCoreEvents, courseBuilderCoreFunctions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import {
|
|
2
|
+
coreInngest,
|
|
3
|
+
createInngestMiddleware,
|
|
4
|
+
defineCourseBuilderFunctions
|
|
5
|
+
} from "./chunk-Y5X5J55Z.js";
|
|
6
|
+
import {
|
|
7
|
+
CourseBuilder
|
|
8
|
+
} from "./chunk-ECNJPNPU.js";
|
|
9
|
+
import {
|
|
10
|
+
createActionURL,
|
|
11
|
+
setEnvDefaults
|
|
12
|
+
} from "./chunk-4LZZLN6T.js";
|
|
13
|
+
import "./chunk-E6HV6TNI.js";
|
|
14
|
+
import {
|
|
15
|
+
CourseBuilderInternal
|
|
16
|
+
} from "./chunk-G63YAJF2.js";
|
|
17
|
+
import "./chunk-5O4UO4IR.js";
|
|
18
|
+
import "./chunk-W7YAT4NR.js";
|
|
19
|
+
import "./chunk-4QQA3TC2.js";
|
|
20
|
+
import "./chunk-KNC7QVGZ.js";
|
|
21
|
+
import "./chunk-4TSEPUSC.js";
|
|
22
|
+
import "./chunk-YFLGJIMA.js";
|
|
23
|
+
import "./chunk-JFR7XO72.js";
|
|
24
|
+
import "./chunk-WYNH2AWD.js";
|
|
25
|
+
import "./chunk-ZFZNN4E5.js";
|
|
26
|
+
import "./chunk-4EQQSW57.js";
|
|
27
|
+
import "./chunk-VEKYIR7I.js";
|
|
28
|
+
import "./chunk-F3KUYN5I.js";
|
|
29
|
+
import "./chunk-7FCQOLKL.js";
|
|
30
|
+
import "./chunk-22AMOZYZ.js";
|
|
31
|
+
import {
|
|
32
|
+
logger
|
|
33
|
+
} from "./chunk-AZLUMIIF.js";
|
|
34
|
+
import "./chunk-ODSSRMD2.js";
|
|
35
|
+
import "./chunk-WGAPYIUP.js";
|
|
36
|
+
|
|
37
|
+
// src/index.ts
|
|
38
|
+
import {
|
|
39
|
+
commerceFunctionsAfterResourceChat,
|
|
40
|
+
commerceFunctionsBeforeResourceChat
|
|
41
|
+
} from "@coursebuilder/commerce/functions";
|
|
42
|
+
import {
|
|
43
|
+
PURCHASE_BENEFITS_ATTACHED_EVENT,
|
|
44
|
+
TEAM_SEAT_REDEMPTION_CREATED_EVENT
|
|
45
|
+
} from "@coursebuilder/core/events/commerce";
|
|
46
|
+
|
|
47
|
+
// src/resource-chat.ts
|
|
48
|
+
import { NonRetriableError } from "inngest";
|
|
49
|
+
import { Liquid } from "liquidjs";
|
|
50
|
+
import { z } from "zod";
|
|
51
|
+
|
|
52
|
+
// src/streaming-chat-prompt-executor.ts
|
|
53
|
+
async function streamingChatPromptExecutor({
|
|
54
|
+
requestId,
|
|
55
|
+
promptMessages,
|
|
56
|
+
model,
|
|
57
|
+
provider
|
|
58
|
+
}) {
|
|
59
|
+
const result = await provider.createChatCompletion({
|
|
60
|
+
messages: promptMessages,
|
|
61
|
+
chatId: requestId,
|
|
62
|
+
model
|
|
63
|
+
});
|
|
64
|
+
if (!result) {
|
|
65
|
+
throw new Error("Chat completion returned null");
|
|
66
|
+
}
|
|
67
|
+
if ("error" in result) {
|
|
68
|
+
throw new Error(result.error);
|
|
69
|
+
}
|
|
70
|
+
const message = result;
|
|
71
|
+
return [
|
|
72
|
+
...promptMessages,
|
|
73
|
+
{
|
|
74
|
+
role: "assistant",
|
|
75
|
+
content: message.content
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/resource-chat.ts
|
|
81
|
+
import {
|
|
82
|
+
ChatResourceSchema,
|
|
83
|
+
RESOURCE_CHAT_REQUEST_EVENT
|
|
84
|
+
} from "@coursebuilder/core/events/resource-chat";
|
|
85
|
+
import {
|
|
86
|
+
RESOURCE_CHAT_REQUEST_EVENT as RESOURCE_CHAT_REQUEST_EVENT2
|
|
87
|
+
} from "@coursebuilder/core/events/resource-chat";
|
|
88
|
+
var resourceChatConfig = {
|
|
89
|
+
id: `resource-chat`,
|
|
90
|
+
name: "Resource Chat",
|
|
91
|
+
rateLimit: {
|
|
92
|
+
key: "event.user.id",
|
|
93
|
+
limit: 5,
|
|
94
|
+
period: "1m"
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var resourceChatTrigger = {
|
|
98
|
+
event: RESOURCE_CHAT_REQUEST_EVENT2
|
|
99
|
+
};
|
|
100
|
+
var resourceChatHandler = async ({
|
|
101
|
+
event,
|
|
102
|
+
step,
|
|
103
|
+
openaiProvider,
|
|
104
|
+
partyProvider,
|
|
105
|
+
db
|
|
106
|
+
}) => {
|
|
107
|
+
const resourceId = event.data.resourceId;
|
|
108
|
+
const workflowTrigger = event.data.selectedWorkflow;
|
|
109
|
+
const currentUserMessage = event.data.messages[event.data.messages.length - 1];
|
|
110
|
+
if (currentUserMessage?.content) {
|
|
111
|
+
await step.run(
|
|
112
|
+
`partykit broadcast user prompt [${resourceId}]`,
|
|
113
|
+
async () => {
|
|
114
|
+
await partyProvider.broadcastMessage({
|
|
115
|
+
body: {
|
|
116
|
+
body: currentUserMessage.content,
|
|
117
|
+
requestId: resourceId,
|
|
118
|
+
name: "resource.chat.prompted",
|
|
119
|
+
// @ts-expect-error
|
|
120
|
+
userId: event.user.id
|
|
121
|
+
},
|
|
122
|
+
roomId: resourceId
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const resource = await step.run("get the resource", async () => {
|
|
128
|
+
return db.getContentResource(resourceId);
|
|
129
|
+
});
|
|
130
|
+
if (!resource) {
|
|
131
|
+
throw new NonRetriableError(`Resource not found for id (${resourceId})`);
|
|
132
|
+
}
|
|
133
|
+
const videoResource = await step.run("get the video resource", async () => {
|
|
134
|
+
return db.getVideoResource(resource.resources?.[0]?.resource.id);
|
|
135
|
+
});
|
|
136
|
+
const messages = await resourceChatWorkflowExecutor({
|
|
137
|
+
db,
|
|
138
|
+
openaiProvider,
|
|
139
|
+
partyProvider,
|
|
140
|
+
step,
|
|
141
|
+
workflowTrigger,
|
|
142
|
+
resourceId,
|
|
143
|
+
resource: {
|
|
144
|
+
...videoResource,
|
|
145
|
+
...resource,
|
|
146
|
+
...resource.fields,
|
|
147
|
+
resources: resource.resources ?? []
|
|
148
|
+
},
|
|
149
|
+
messages: event.data.messages,
|
|
150
|
+
// @ts-expect-error
|
|
151
|
+
user: event.user
|
|
152
|
+
});
|
|
153
|
+
return { resource: { ...videoResource, ...resource }, messages };
|
|
154
|
+
};
|
|
155
|
+
async function resourceChatWorkflowExecutor({
|
|
156
|
+
step,
|
|
157
|
+
workflowTrigger,
|
|
158
|
+
resourceId,
|
|
159
|
+
messages,
|
|
160
|
+
resource,
|
|
161
|
+
user,
|
|
162
|
+
openaiProvider,
|
|
163
|
+
partyProvider,
|
|
164
|
+
db,
|
|
165
|
+
model
|
|
166
|
+
}) {
|
|
167
|
+
const basicPrompt = {
|
|
168
|
+
id: "basic",
|
|
169
|
+
name: "Basic",
|
|
170
|
+
type: "prompt",
|
|
171
|
+
fields: {
|
|
172
|
+
body: `# Instructions
|
|
173
|
+
Pause. Take a deep breath and think. This is important. Think step by step.
|
|
174
|
+
|
|
175
|
+
You are serving as a writing assistant for a content creator that is publishing a {% if transcript %}video based{% endif %} post for software developers. The content creator will ask questions and expect concise answers that aren't corny or generic.
|
|
176
|
+
|
|
177
|
+
Keep responses scoped to the post and it's direct contents. Do not include additional information.
|
|
178
|
+
Do not include information that is not directly related to the post or the {% if transcript %}video{% endif %}.
|
|
179
|
+
|
|
180
|
+
Use simple language.
|
|
181
|
+
|
|
182
|
+
Use only most popular 2000 english words {% if transcript %}and words used in the transcript{% endif %}.
|
|
183
|
+
Simple is better.
|
|
184
|
+
Flourish is bad.
|
|
185
|
+
**People will hate you if you try to sound clever.**
|
|
186
|
+
|
|
187
|
+
{% if wordLevelSrt %} add screenshots from the video when they are relevant and would be useful to
|
|
188
|
+
the reader using the following template replacing {{timestampInSeconds}} with the time noted in the transcript:
|
|
189
|
+
|
|
190
|
+

|
|
191
|
+
be precise with the timestamps! {% if wordLevelSrt %} use this word level SRT to get the exact timestamp:
|
|
192
|
+
|
|
193
|
+
word level srt start
|
|
194
|
+
{{wordLevelSrt}} {% endif %}
|
|
195
|
+
|
|
196
|
+
word level srt end
|
|
197
|
+
{% endif %}
|
|
198
|
+
|
|
199
|
+
Get it right and there's $200 cash gratuity in it for you ;)
|
|
200
|
+
|
|
201
|
+
{% if transcript %}The goal is to build a really good written version of the existing video, not edit the video itself. The video is done.
|
|
202
|
+
|
|
203
|
+
The post transcript is the final representation of the video. The post transcript is the source of truth.{% endif %}
|
|
204
|
+
|
|
205
|
+
Keep the language simple and don't use words not in the post {% if transcript %}transcript{% endif %}.
|
|
206
|
+
|
|
207
|
+
{% if transcript %}Do not make direct references to the video.
|
|
208
|
+
Do not make direct references to the transcript.{% endif %}
|
|
209
|
+
Do not make direct references to the content creator.
|
|
210
|
+
Do not make direct references to 'the post'.
|
|
211
|
+
Jump right to the point.
|
|
212
|
+
|
|
213
|
+
Post Type: {{type}}
|
|
214
|
+
|
|
215
|
+
Post Title: {{title}}
|
|
216
|
+
|
|
217
|
+
{% if transcript %}Post Transcript: {{transcript}}{% endif %}
|
|
218
|
+
|
|
219
|
+
Post Body: {{body}}
|
|
220
|
+
`
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
let prompt = workflowTrigger === "basic" ? basicPrompt : await step.run("Load Prompt", async () => {
|
|
224
|
+
return db.getContentResource(workflowTrigger);
|
|
225
|
+
});
|
|
226
|
+
if (!prompt) {
|
|
227
|
+
prompt = basicPrompt;
|
|
228
|
+
}
|
|
229
|
+
let systemPrompt = {
|
|
230
|
+
role: "system",
|
|
231
|
+
content: prompt.fields.body
|
|
232
|
+
};
|
|
233
|
+
let seedMessages = [];
|
|
234
|
+
try {
|
|
235
|
+
const actionParsed = z.array(
|
|
236
|
+
z.object({
|
|
237
|
+
role: z.enum([
|
|
238
|
+
"system" /* System */,
|
|
239
|
+
"user" /* User */,
|
|
240
|
+
"assistant" /* Assistant */,
|
|
241
|
+
"tool" /* Tool */
|
|
242
|
+
]),
|
|
243
|
+
content: z.string()
|
|
244
|
+
})
|
|
245
|
+
).parse(JSON.parse(prompt.fields.body));
|
|
246
|
+
const actionMessages = [];
|
|
247
|
+
for (const actionMessage of actionParsed) {
|
|
248
|
+
const liquidParsedContent = await step.run(
|
|
249
|
+
"parse json content",
|
|
250
|
+
async () => {
|
|
251
|
+
const engine = new Liquid();
|
|
252
|
+
const contentString = typeof actionMessage.content === "string" ? actionMessage.content : JSON.stringify(actionMessage.content);
|
|
253
|
+
return await engine.parseAndRender(contentString, {
|
|
254
|
+
...resource
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
actionMessages.push({
|
|
259
|
+
role: actionMessage.role,
|
|
260
|
+
content: liquidParsedContent
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (actionMessages.length > 0) {
|
|
264
|
+
;
|
|
265
|
+
[
|
|
266
|
+
systemPrompt = {
|
|
267
|
+
role: "system",
|
|
268
|
+
content: prompt.fields.body
|
|
269
|
+
},
|
|
270
|
+
...seedMessages
|
|
271
|
+
] = actionMessages;
|
|
272
|
+
}
|
|
273
|
+
} catch (e) {
|
|
274
|
+
systemPrompt = await step.run(`parse system prompt`, async () => {
|
|
275
|
+
try {
|
|
276
|
+
const engine = new Liquid();
|
|
277
|
+
const originalSystemPrompt = systemPrompt;
|
|
278
|
+
const contentString = typeof originalSystemPrompt.content === "string" ? originalSystemPrompt.content : JSON.stringify(originalSystemPrompt.content);
|
|
279
|
+
return {
|
|
280
|
+
role: originalSystemPrompt.role,
|
|
281
|
+
content: await engine.parseAndRender(contentString || "", resource)
|
|
282
|
+
};
|
|
283
|
+
} catch (e2) {
|
|
284
|
+
logger.error(e2 instanceof Error ? e2 : new Error(String(e2)), {
|
|
285
|
+
context: "co-gardener.resource-chat.system-prompt-render",
|
|
286
|
+
resourceId
|
|
287
|
+
});
|
|
288
|
+
return {
|
|
289
|
+
role: "system",
|
|
290
|
+
content: prompt.fields.body
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (messages.length <= 2 && systemPrompt) {
|
|
296
|
+
messages = [systemPrompt, ...seedMessages, ...messages];
|
|
297
|
+
}
|
|
298
|
+
const currentUserMessage = messages[messages.length - 1];
|
|
299
|
+
const currentResourceMetadata = messages[messages.length - 2];
|
|
300
|
+
messages = await step.run("answer the user prompt", async () => {
|
|
301
|
+
if (!currentUserMessage) {
|
|
302
|
+
throw new Error("No user message");
|
|
303
|
+
}
|
|
304
|
+
const engine = new Liquid();
|
|
305
|
+
const currentUserContentString = typeof currentUserMessage.content === "string" ? currentUserMessage.content : JSON.stringify(currentUserMessage.content);
|
|
306
|
+
currentUserMessage.content = await engine.parseAndRender(
|
|
307
|
+
currentUserContentString ?? "",
|
|
308
|
+
resource
|
|
309
|
+
);
|
|
310
|
+
if (currentResourceMetadata) {
|
|
311
|
+
const metadataContentString = typeof currentResourceMetadata.content === "string" ? currentResourceMetadata.content : JSON.stringify(currentResourceMetadata.content);
|
|
312
|
+
currentResourceMetadata.content = await engine.parseAndRender(
|
|
313
|
+
metadataContentString ?? "",
|
|
314
|
+
resource
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return streamingChatPromptExecutor({
|
|
318
|
+
requestId: resourceId,
|
|
319
|
+
promptMessages: messages,
|
|
320
|
+
model: prompt.fields.model || model || "gpt-4-turbo",
|
|
321
|
+
provider: openaiProvider
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
await step.run(`partykit broadcast [${resourceId}]`, async () => {
|
|
325
|
+
return await partyProvider.broadcastMessage({
|
|
326
|
+
body: {
|
|
327
|
+
body: messages,
|
|
328
|
+
requestId: resourceId,
|
|
329
|
+
name: "resource.chat.completed",
|
|
330
|
+
metadata: {
|
|
331
|
+
workflow: workflowTrigger
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
roomId: resourceId
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
return messages;
|
|
338
|
+
}
|
|
339
|
+
var resourceChat = {
|
|
340
|
+
config: resourceChatConfig,
|
|
341
|
+
trigger: resourceChatTrigger,
|
|
342
|
+
handler: resourceChatHandler
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// src/index.ts
|
|
346
|
+
import { coreVideoProcessingFunctions } from "@coursebuilder/video-processing/functions";
|
|
347
|
+
var courseBuilderCoreFunctions = defineCourseBuilderFunctions([
|
|
348
|
+
...coreVideoProcessingFunctions,
|
|
349
|
+
...commerceFunctionsBeforeResourceChat,
|
|
350
|
+
resourceChat,
|
|
351
|
+
...commerceFunctionsAfterResourceChat
|
|
352
|
+
]);
|
|
353
|
+
export {
|
|
354
|
+
CourseBuilder,
|
|
355
|
+
CourseBuilderInternal,
|
|
356
|
+
PURCHASE_BENEFITS_ATTACHED_EVENT,
|
|
357
|
+
TEAM_SEAT_REDEMPTION_CREATED_EVENT,
|
|
358
|
+
coreInngest,
|
|
359
|
+
courseBuilderCoreFunctions,
|
|
360
|
+
createActionURL,
|
|
361
|
+
createInngestMiddleware,
|
|
362
|
+
defineCourseBuilderFunctions,
|
|
363
|
+
setEnvDefaults
|
|
364
|
+
};
|
|
365
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/resource-chat.ts","../src/streaming-chat-prompt-executor.ts"],"sourcesContent":["import {\n\tcommerceFunctionsAfterResourceChat,\n\tcommerceFunctionsBeforeResourceChat,\n} from '@coursebuilder/commerce/functions'\nimport {\n\tPURCHASE_BENEFITS_ATTACHED_EVENT,\n\tTEAM_SEAT_REDEMPTION_CREATED_EVENT,\n} from '@coursebuilder/core/events/commerce'\nimport { resourceChat } from './resource-chat'\nimport { coreVideoProcessingFunctions } from '@coursebuilder/video-processing/functions'\n\nimport { defineCourseBuilderFunctions } from './create-inngest-middleware'\n\nexport { CourseBuilder, createActionURL, setEnvDefaults } from './http'\nexport type { CourseBuilderConfig } from './http'\nexport { CourseBuilderInternal } from './http-router'\n\n/** @deprecated Import this provider-neutral event map from `@coursebuilder/core/events`. */\nexport type CourseBuilderCoreEvents =\n\timport('@coursebuilder/core/events').CourseBuilderCoreEvents\n\nexport { PURCHASE_BENEFITS_ATTACHED_EVENT, TEAM_SEAT_REDEMPTION_CREATED_EVENT }\n\nexport const courseBuilderCoreFunctions = defineCourseBuilderFunctions([\n\t...coreVideoProcessingFunctions,\n\t...commerceFunctionsBeforeResourceChat,\n\tresourceChat,\n\t...commerceFunctionsAfterResourceChat,\n])\n\nexport {\n\tcoreInngest,\n\tcreateInngestMiddleware,\n\tdefineCourseBuilderFunctions,\n} from './create-inngest-middleware'\nexport type {\n\tCoreInngest,\n\tCoreInngestContext,\n\tCourseBuilderFunctionDefinition,\n\tCourseBuilderHandlerInput,\n\tCoreInngestFunctionInput,\n\tCoreInngestHandler,\n\tCoreInngestTrigger,\n} from './create-inngest-middleware'\n","import { NonRetriableError } from 'inngest'\nimport { Liquid } from 'liquidjs'\nimport { z } from 'zod'\n\nimport type { ServerAdapter } from './adapter'\nimport { logger } from './runtime/logger'\nimport { LlmProviderConfig } from '@coursebuilder/core/providers/openai'\nimport { PartyProviderConfig } from '@coursebuilder/core/providers/partykit'\nimport { User } from '@coursebuilder/core/schemas'\nimport {\n\tCoreInngestFunctionInput,\n\tCoreInngestHandler,\n\tCoreInngestTrigger,\n} from './create-inngest-middleware'\nimport {\n\tChatCompletionRequestMessage,\n\tstreamingChatPromptExecutor,\n} from './streaming-chat-prompt-executor'\n\n/** @deprecated Import event contracts from `@coursebuilder/core/events`. */\nexport {\n\tChatResourceSchema,\n\ttype ChatResource,\n\tRESOURCE_CHAT_REQUEST_EVENT,\n\ttype ResourceChat,\n} from '@coursebuilder/core/events/resource-chat'\nimport {\n\tChatResourceSchema,\n\ttype ChatResource,\n\tRESOURCE_CHAT_REQUEST_EVENT,\n} from '@coursebuilder/core/events/resource-chat'\n\nexport const resourceChatConfig = {\n\tid: `resource-chat`,\n\tname: 'Resource Chat',\n\trateLimit: {\n\t\tkey: 'event.user.id',\n\t\tlimit: 5,\n\t\tperiod: '1m' as `${number}m`,\n\t},\n}\n\nexport const resourceChatTrigger: CoreInngestTrigger = {\n\tevent: RESOURCE_CHAT_REQUEST_EVENT,\n}\n\n// Define ChatCompletionRequestMessageRoleEnum\nexport enum ChatCompletionRequestMessageRoleEnum {\n\tSystem = 'system',\n\tUser = 'user',\n\tAssistant = 'assistant',\n\tTool = 'tool',\n}\n\n/**\n * TODO: Cancellation conditions need to be added $$\n */\nexport const resourceChatHandler: CoreInngestHandler = async ({\n\tevent,\n\tstep,\n\topenaiProvider,\n\tpartyProvider,\n\tdb,\n}: CoreInngestFunctionInput) => {\n\tconst resourceId = event.data.resourceId\n\tconst workflowTrigger = event.data.selectedWorkflow\n\n\tconst currentUserMessage = event.data.messages[event.data.messages.length - 1]\n\n\tif (currentUserMessage?.content) {\n\t\tawait step.run(\n\t\t\t`partykit broadcast user prompt [${resourceId}]`,\n\t\t\tasync () => {\n\t\t\t\tawait partyProvider.broadcastMessage({\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tbody: currentUserMessage.content,\n\t\t\t\t\t\trequestId: resourceId,\n\t\t\t\t\t\tname: 'resource.chat.prompted',\n\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\tuserId: event.user.id,\n\t\t\t\t\t},\n\t\t\t\t\troomId: resourceId,\n\t\t\t\t})\n\t\t\t},\n\t\t)\n\t}\n\n\tconst resource = await step.run('get the resource', async () => {\n\t\treturn db.getContentResource(resourceId)\n\t})\n\n\tif (!resource) {\n\t\tthrow new NonRetriableError(`Resource not found for id (${resourceId})`)\n\t}\n\n\tconst videoResource = await step.run('get the video resource', async () => {\n\t\treturn db.getVideoResource(resource.resources?.[0]?.resource.id)\n\t})\n\n\tconst messages = await resourceChatWorkflowExecutor({\n\t\tdb,\n\t\topenaiProvider,\n\t\tpartyProvider,\n\t\tstep,\n\t\tworkflowTrigger,\n\t\tresourceId,\n\n\t\tresource: {\n\t\t\t...videoResource,\n\t\t\t...resource,\n\t\t\t...resource.fields,\n\t\t\tresources: resource.resources ?? [],\n\t\t},\n\t\tmessages: event.data.messages,\n\t\t// @ts-expect-error\n\t\tuser: event.user,\n\t})\n\n\treturn { resource: { ...videoResource, ...resource }, messages }\n}\n\n/**\n * loads the workflow from sanity based on the trigger and then executes the workflow using the `resource` as\n * input that is parsed by liquid into the prompt\n *\n * This treats the system prompt as \"special\" from the loaded workflow since it is added to the beginning of the prompt\n * in the chat context, but additional steps are executed as normal\n *\n * @param step\n * @param workflowTrigger\n * @param resourceId\n * @param messages\n * @param resource\n * @param currentFeedback\n */\nexport async function resourceChatWorkflowExecutor({\n\tstep,\n\tworkflowTrigger,\n\tresourceId,\n\tmessages,\n\tresource,\n\tuser,\n\topenaiProvider,\n\tpartyProvider,\n\tdb,\n\tmodel,\n}: {\n\topenaiProvider: LlmProviderConfig\n\tpartyProvider: PartyProviderConfig\n\tdb: ServerAdapter\n\tresource: ChatResource\n\tstep: any\n\tworkflowTrigger: string\n\tresourceId: string\n\tmessages: ChatCompletionRequestMessage[]\n\tuser: User\n\tmodel?: string\n}) {\n\tconst basicPrompt = {\n\t\tid: 'basic',\n\t\tname: 'Basic',\n\t\ttype: 'prompt',\n\t\tfields: {\n\t\t\tbody: `# Instructions\nPause. Take a deep breath and think. This is important. Think step by step.\n\nYou are serving as a writing assistant for a content creator that is publishing a {% if transcript %}video based{% endif %} post for software developers. The content creator will ask questions and expect concise answers that aren't corny or generic.\n\nKeep responses scoped to the post and it's direct contents. Do not include additional information.\nDo not include information that is not directly related to the post or the {% if transcript %}video{% endif %}.\n\nUse simple language.\n\nUse only most popular 2000 english words {% if transcript %}and words used in the transcript{% endif %}.\nSimple is better.\nFlourish is bad.\n**People will hate you if you try to sound clever.**\n\n{% if wordLevelSrt %} add screenshots from the video when they are relevant and would be useful to\nthe reader using the following template replacing {{timestampInSeconds}} with the time noted in the transcript:\n\n\nbe precise with the timestamps! {% if wordLevelSrt %} use this word level SRT to get the exact timestamp:\n\nword level srt start\n{{wordLevelSrt}} {% endif %}\n\nword level srt end\n{% endif %}\n\nGet it right and there's $200 cash gratuity in it for you ;)\n\n{% if transcript %}The goal is to build a really good written version of the existing video, not edit the video itself. The video is done.\n\nThe post transcript is the final representation of the video. The post transcript is the source of truth.{% endif %}\n\nKeep the language simple and don't use words not in the post {% if transcript %}transcript{% endif %}.\n\n{% if transcript %}Do not make direct references to the video.\nDo not make direct references to the transcript.{% endif %}\nDo not make direct references to the content creator.\nDo not make direct references to 'the post'.\nJump right to the point.\n\nPost Type: {{type}}\n\nPost Title: {{title}}\n\n{% if transcript %}Post Transcript: {{transcript}}{% endif %}\n\nPost Body: {{body}}\n`,\n\t\t},\n\t}\n\n\tlet prompt =\n\t\tworkflowTrigger === 'basic'\n\t\t\t? basicPrompt\n\t\t\t: await step.run('Load Prompt', async () => {\n\t\t\t\t\treturn db.getContentResource(workflowTrigger)\n\t\t\t\t})\n\n\tif (!prompt) {\n\t\tprompt = basicPrompt\n\t}\n\n\tlet systemPrompt: ChatCompletionRequestMessage = {\n\t\trole: 'system',\n\t\tcontent: prompt.fields.body,\n\t}\n\tlet seedMessages: ChatCompletionRequestMessage[] = []\n\n\ttry {\n\t\tconst actionParsed = z\n\t\t\t.array(\n\t\t\t\tz.object({\n\t\t\t\t\trole: z.enum([\n\t\t\t\t\t\tChatCompletionRequestMessageRoleEnum.System,\n\t\t\t\t\t\tChatCompletionRequestMessageRoleEnum.User,\n\t\t\t\t\t\tChatCompletionRequestMessageRoleEnum.Assistant,\n\t\t\t\t\t\tChatCompletionRequestMessageRoleEnum.Tool,\n\t\t\t\t\t]),\n\t\t\t\t\tcontent: z.string(),\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.parse(JSON.parse(prompt.fields.body)) as Array<{\n\t\t\trole: ChatCompletionRequestMessageRoleEnum\n\t\t\tcontent: string\n\t\t}>\n\n\t\tconst actionMessages: ChatCompletionRequestMessage[] = []\n\t\tfor (const actionMessage of actionParsed) {\n\t\t\tconst liquidParsedContent = await step.run(\n\t\t\t\t'parse json content',\n\t\t\t\tasync () => {\n\t\t\t\t\tconst engine = new Liquid()\n\t\t\t\t\tconst contentString =\n\t\t\t\t\t\ttypeof actionMessage.content === 'string'\n\t\t\t\t\t\t\t? actionMessage.content\n\t\t\t\t\t\t\t: JSON.stringify(actionMessage.content)\n\t\t\t\t\treturn await engine.parseAndRender(contentString, {\n\t\t\t\t\t\t...resource,\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t)\n\n\t\t\tactionMessages.push({\n\t\t\t\trole: actionMessage.role,\n\t\t\t\tcontent: liquidParsedContent,\n\t\t\t})\n\t\t}\n\t\tif (actionMessages.length > 0) {\n\t\t\t;[\n\t\t\t\tsystemPrompt = {\n\t\t\t\t\trole: 'system',\n\t\t\t\t\tcontent: prompt.fields.body,\n\t\t\t\t},\n\t\t\t\t...seedMessages\n\t\t\t] = actionMessages\n\t\t}\n\t} catch (e: any) {\n\t\t// if the prompt action content is not valid json, we assume it's just text\n\t\tsystemPrompt = await step.run(`parse system prompt`, async () => {\n\t\t\ttry {\n\t\t\t\tconst engine = new Liquid()\n\t\t\t\tconst originalSystemPrompt = systemPrompt // Store reference before reassignment\n\t\t\t\tconst contentString =\n\t\t\t\t\ttypeof originalSystemPrompt.content === 'string'\n\t\t\t\t\t\t? originalSystemPrompt.content\n\t\t\t\t\t\t: JSON.stringify(originalSystemPrompt.content)\n\t\t\t\treturn {\n\t\t\t\t\trole: originalSystemPrompt.role,\n\t\t\t\t\tcontent: await engine.parseAndRender(contentString || '', resource),\n\t\t\t\t}\n\t\t\t} catch (e: any) {\n\t\t\t\tlogger.error(e instanceof Error ? e : new Error(String(e)), {\n\t\t\t\t\tcontext: 'co-gardener.resource-chat.system-prompt-render',\n\t\t\t\t\tresourceId,\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\trole: 'system',\n\t\t\t\t\tcontent: prompt.fields.body,\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tif (messages.length <= 2 && systemPrompt) {\n\t\tmessages = [systemPrompt, ...seedMessages, ...messages]\n\t}\n\n\tconst currentUserMessage = messages[messages.length - 1]\n\tconst currentResourceMetadata = messages[messages.length - 2]\n\n\tmessages = await step.run('answer the user prompt', async () => {\n\t\tif (!currentUserMessage) {\n\t\t\tthrow new Error('No user message')\n\t\t}\n\n\t\tconst engine = new Liquid()\n\t\tconst currentUserContentString =\n\t\t\ttypeof currentUserMessage.content === 'string'\n\t\t\t\t? currentUserMessage.content\n\t\t\t\t: JSON.stringify(currentUserMessage.content)\n\n\t\tcurrentUserMessage.content = await engine.parseAndRender(\n\t\t\tcurrentUserContentString ?? '',\n\t\t\tresource,\n\t\t)\n\n\t\tif (currentResourceMetadata) {\n\t\t\tconst metadataContentString =\n\t\t\t\ttypeof currentResourceMetadata.content === 'string'\n\t\t\t\t\t? currentResourceMetadata.content\n\t\t\t\t\t: JSON.stringify(currentResourceMetadata.content)\n\t\t\tcurrentResourceMetadata.content = await engine.parseAndRender(\n\t\t\t\tmetadataContentString ?? '',\n\t\t\t\tresource,\n\t\t\t)\n\t\t}\n\n\t\treturn streamingChatPromptExecutor({\n\t\t\trequestId: resourceId,\n\t\t\tpromptMessages: messages,\n\t\t\tmodel: prompt.fields.model || model || 'gpt-4-turbo',\n\t\t\tprovider: openaiProvider,\n\t\t})\n\t})\n\n\tawait step.run(`partykit broadcast [${resourceId}]`, async () => {\n\t\treturn await partyProvider.broadcastMessage({\n\t\t\tbody: {\n\t\t\t\tbody: messages,\n\t\t\t\trequestId: resourceId,\n\t\t\t\tname: 'resource.chat.completed',\n\t\t\t\tmetadata: {\n\t\t\t\t\tworkflow: workflowTrigger,\n\t\t\t\t},\n\t\t\t},\n\t\t\troomId: resourceId,\n\t\t})\n\t})\n\n\treturn messages\n}\n\nexport const resourceChat = {\n\tconfig: resourceChatConfig,\n\ttrigger: resourceChatTrigger,\n\thandler: resourceChatHandler,\n}\n","import { type ModelMessage } from 'ai'\n\nimport { LlmProviderConfig } from '@coursebuilder/core/providers/openai'\nimport { AIMessage, type AIOutput } from '@coursebuilder/core/types'\n\nexport type ChatCompletionRequestMessage = ModelMessage\n\ntype PromptStepOptions = {\n\trequestId: string\n\tpromptMessages: ModelMessage[]\n\tmodel: string\n\tprovider: LlmProviderConfig\n}\n\nexport async function streamingChatPromptExecutor({\n\trequestId,\n\tpromptMessages,\n\tmodel,\n\tprovider,\n}: PromptStepOptions) {\n\tconst result: AIOutput | null = await provider.createChatCompletion({\n\t\tmessages: promptMessages,\n\t\tchatId: requestId,\n\t\tmodel,\n\t})\n\n\tif (!result) {\n\t\tthrow new Error('Chat completion returned null')\n\t}\n\n\tif ('error' in result) {\n\t\tthrow new Error(result.error)\n\t}\n\n\tconst message = result as AIMessage\n\treturn [\n\t\t...promptMessages,\n\t\t{\n\t\t\trole: 'assistant',\n\t\t\tcontent: message.content,\n\t\t} as ModelMessage,\n\t]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACC;AAAA,EACA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,OACM;;;ACPP,SAAS,yBAAyB;AAClC,SAAS,cAAc;AACvB,SAAS,SAAS;;;ACYlB,eAAsB,4BAA4B;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAsB;AACrB,QAAM,SAA0B,MAAM,SAAS,qBAAqB;AAAA,IACnE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EACD,CAAC;AAED,MAAI,CAAC,QAAQ;AACZ,UAAM,IAAI,MAAM,+BAA+B;AAAA,EAChD;AAEA,MAAI,WAAW,QAAQ;AACtB,UAAM,IAAI,MAAM,OAAO,KAAK;AAAA,EAC7B;AAEA,QAAM,UAAU;AAChB,SAAO;AAAA,IACN,GAAG;AAAA,IACH;AAAA,MACC,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,IAClB;AAAA,EACD;AACD;;;ADtBA;AAAA,EACC;AAAA,EAEA;AAAA,OAEM;AACP;AAAA,EAGC,+BAAAA;AAAA,OACM;AAEA,IAAM,qBAAqB;AAAA,EACjC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,WAAW;AAAA,IACV,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,EACT;AACD;AAEO,IAAM,sBAA0C;AAAA,EACtD,OAAOA;AACR;AAaO,IAAM,sBAA0C,OAAO;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,MAAgC;AAC/B,QAAM,aAAa,MAAM,KAAK;AAC9B,QAAM,kBAAkB,MAAM,KAAK;AAEnC,QAAM,qBAAqB,MAAM,KAAK,SAAS,MAAM,KAAK,SAAS,SAAS,CAAC;AAE7E,MAAI,oBAAoB,SAAS;AAChC,UAAM,KAAK;AAAA,MACV,mCAAmC,UAAU;AAAA,MAC7C,YAAY;AACX,cAAM,cAAc,iBAAiB;AAAA,UACpC,MAAM;AAAA,YACL,MAAM,mBAAmB;AAAA,YACzB,WAAW;AAAA,YACX,MAAM;AAAA;AAAA,YAEN,QAAQ,MAAM,KAAK;AAAA,UACpB;AAAA,UACA,QAAQ;AAAA,QACT,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,QAAM,WAAW,MAAM,KAAK,IAAI,oBAAoB,YAAY;AAC/D,WAAO,GAAG,mBAAmB,UAAU;AAAA,EACxC,CAAC;AAED,MAAI,CAAC,UAAU;AACd,UAAM,IAAI,kBAAkB,8BAA8B,UAAU,GAAG;AAAA,EACxE;AAEA,QAAM,gBAAgB,MAAM,KAAK,IAAI,0BAA0B,YAAY;AAC1E,WAAO,GAAG,iBAAiB,SAAS,YAAY,CAAC,GAAG,SAAS,EAAE;AAAA,EAChE,CAAC;AAED,QAAM,WAAW,MAAM,6BAA6B;AAAA,IACnD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAEA,UAAU;AAAA,MACT,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG,SAAS;AAAA,MACZ,WAAW,SAAS,aAAa,CAAC;AAAA,IACnC;AAAA,IACA,UAAU,MAAM,KAAK;AAAA;AAAA,IAErB,MAAM,MAAM;AAAA,EACb,CAAC;AAED,SAAO,EAAE,UAAU,EAAE,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS;AAChE;AAgBA,eAAsB,6BAA6B;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAWG;AACF,QAAM,cAAc;AAAA,IACnB,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,MACP,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiDP;AAAA,EACD;AAEA,MAAI,SACH,oBAAoB,UACjB,cACA,MAAM,KAAK,IAAI,eAAe,YAAY;AAC1C,WAAO,GAAG,mBAAmB,eAAe;AAAA,EAC7C,CAAC;AAEJ,MAAI,CAAC,QAAQ;AACZ,aAAS;AAAA,EACV;AAEA,MAAI,eAA6C;AAAA,IAChD,MAAM;AAAA,IACN,SAAS,OAAO,OAAO;AAAA,EACxB;AACA,MAAI,eAA+C,CAAC;AAEpD,MAAI;AACH,UAAM,eAAe,EACnB;AAAA,MACA,EAAE,OAAO;AAAA,QACR,MAAM,EAAE,KAAK;AAAA,UACZ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD,CAAC;AAAA,QACD,SAAS,EAAE,OAAO;AAAA,MACnB,CAAC;AAAA,IACF,EACC,MAAM,KAAK,MAAM,OAAO,OAAO,IAAI,CAAC;AAKtC,UAAM,iBAAiD,CAAC;AACxD,eAAW,iBAAiB,cAAc;AACzC,YAAM,sBAAsB,MAAM,KAAK;AAAA,QACtC;AAAA,QACA,YAAY;AACX,gBAAM,SAAS,IAAI,OAAO;AAC1B,gBAAM,gBACL,OAAO,cAAc,YAAY,WAC9B,cAAc,UACd,KAAK,UAAU,cAAc,OAAO;AACxC,iBAAO,MAAM,OAAO,eAAe,eAAe;AAAA,YACjD,GAAG;AAAA,UACJ,CAAC;AAAA,QACF;AAAA,MACD;AAEA,qBAAe,KAAK;AAAA,QACnB,MAAM,cAAc;AAAA,QACpB,SAAS;AAAA,MACV,CAAC;AAAA,IACF;AACA,QAAI,eAAe,SAAS,GAAG;AAC9B;AAAC;AAAA,QACA,eAAe;AAAA,UACd,MAAM;AAAA,UACN,SAAS,OAAO,OAAO;AAAA,QACxB;AAAA,QACA,GAAG;AAAA,MACJ,IAAI;AAAA,IACL;AAAA,EACD,SAAS,GAAQ;AAEhB,mBAAe,MAAM,KAAK,IAAI,uBAAuB,YAAY;AAChE,UAAI;AACH,cAAM,SAAS,IAAI,OAAO;AAC1B,cAAM,uBAAuB;AAC7B,cAAM,gBACL,OAAO,qBAAqB,YAAY,WACrC,qBAAqB,UACrB,KAAK,UAAU,qBAAqB,OAAO;AAC/C,eAAO;AAAA,UACN,MAAM,qBAAqB;AAAA,UAC3B,SAAS,MAAM,OAAO,eAAe,iBAAiB,IAAI,QAAQ;AAAA,QACnE;AAAA,MACD,SAASC,IAAQ;AAChB,eAAO,MAAMA,cAAa,QAAQA,KAAI,IAAI,MAAM,OAAOA,EAAC,CAAC,GAAG;AAAA,UAC3D,SAAS;AAAA,UACT;AAAA,QACD,CAAC;AACD,eAAO;AAAA,UACN,MAAM;AAAA,UACN,SAAS,OAAO,OAAO;AAAA,QACxB;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,MAAI,SAAS,UAAU,KAAK,cAAc;AACzC,eAAW,CAAC,cAAc,GAAG,cAAc,GAAG,QAAQ;AAAA,EACvD;AAEA,QAAM,qBAAqB,SAAS,SAAS,SAAS,CAAC;AACvD,QAAM,0BAA0B,SAAS,SAAS,SAAS,CAAC;AAE5D,aAAW,MAAM,KAAK,IAAI,0BAA0B,YAAY;AAC/D,QAAI,CAAC,oBAAoB;AACxB,YAAM,IAAI,MAAM,iBAAiB;AAAA,IAClC;AAEA,UAAM,SAAS,IAAI,OAAO;AAC1B,UAAM,2BACL,OAAO,mBAAmB,YAAY,WACnC,mBAAmB,UACnB,KAAK,UAAU,mBAAmB,OAAO;AAE7C,uBAAmB,UAAU,MAAM,OAAO;AAAA,MACzC,4BAA4B;AAAA,MAC5B;AAAA,IACD;AAEA,QAAI,yBAAyB;AAC5B,YAAM,wBACL,OAAO,wBAAwB,YAAY,WACxC,wBAAwB,UACxB,KAAK,UAAU,wBAAwB,OAAO;AAClD,8BAAwB,UAAU,MAAM,OAAO;AAAA,QAC9C,yBAAyB;AAAA,QACzB;AAAA,MACD;AAAA,IACD;AAEA,WAAO,4BAA4B;AAAA,MAClC,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,OAAO,OAAO,OAAO,SAAS,SAAS;AAAA,MACvC,UAAU;AAAA,IACX,CAAC;AAAA,EACF,CAAC;AAED,QAAM,KAAK,IAAI,uBAAuB,UAAU,KAAK,YAAY;AAChE,WAAO,MAAM,cAAc,iBAAiB;AAAA,MAC3C,MAAM;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,QACN,UAAU;AAAA,UACT,UAAU;AAAA,QACX;AAAA,MACD;AAAA,MACA,QAAQ;AAAA,IACT,CAAC;AAAA,EACF,CAAC;AAED,SAAO;AACR;AAEO,IAAM,eAAe;AAAA,EAC3B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AACV;;;ADzWA,SAAS,oCAAoC;AActC,IAAM,6BAA6B,6BAA6B;AAAA,EACtE,GAAG;AAAA,EACH,GAAG;AAAA,EACH;AAAA,EACA,GAAG;AACJ,CAAC;","names":["RESOURCE_CHAT_REQUEST_EVENT","e"]}
|