Skip to content

Commit

Permalink
Merge branch 'main' into cs-7576-show-error-when-save-request-blocked…
Browse files Browse the repository at this point in the history
…-by-waf
  • Loading branch information
lukemelia committed Nov 28, 2024
2 parents c86979f + 7c91768 commit d17abac
Show file tree
Hide file tree
Showing 88 changed files with 3,601 additions and 637 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build-host.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ jobs:
echo "MATRIX_URL=https://matrix.boxel.ai" >> $GITHUB_ENV
echo "MATRIX_SERVER_NAME=boxel.ai" >> $GITHUB_ENV
echo "EXPERIMENTAL_AI_ENABLED=true" >> $GITHUB_ENV
echo "STRIPE_PAYMENT_LINK=https://buy.stripe.com/00g29k8zLgI35xK000" >> $GITHUB_ENV
elif [ "$INPUT_ENVIRONMENT" = "staging" ]; then
echo "OWN_REALM_URL=https://realms-staging.stack.cards/experiments/" >> $GITHUB_ENV
echo "RESOLVED_BASE_REALM_URL=https://realms-staging.stack.cards/base/" >> $GITHUB_ENV
echo "MATRIX_URL=https://matrix-staging.stack.cards" >> $GITHUB_ENV
echo "MATRIX_SERVER_NAME=stack.cards" >> $GITHUB_ENV
echo "EXPERIMENTAL_AI_ENABLED=true" >> $GITHUB_ENV
echo "STRIPE_PAYMENT_LINK=https://buy.stripe.com/test_9AQdUjgaDePb8lWcMN" >> $GITHUB_ENV
else
echo "unrecognized environment"
exit 1;
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/pr-boxel-host.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
MATRIX_URL: https://matrix-staging.stack.cards
MATRIX_SERVER_NAME: stack.cards
EXPERIMENTAL_AI_ENABLED: true
STRIPE_PAYMENT_LINK: https://buy.stripe.com/test_9AQdUjgaDePb8lWcMN
S3_PREVIEW_BUCKET_NAME: boxel-host-preview.stack.cards
AWS_S3_BUCKET: boxel-host-preview.stack.cards
AWS_REGION: us-east-1
Expand Down Expand Up @@ -92,6 +93,7 @@ jobs:
MATRIX_URL: https://matrix.boxel.ai
MATRIX_SERVER_NAME: boxel.ai
EXPERIMENTAL_AI_ENABLED: true
STRIPE_PAYMENT_LINK: https://buy.stripe.com/00g29k8zLgI35xK000
S3_PREVIEW_BUCKET_NAME: boxel-host-preview.boxel.ai
AWS_S3_BUCKET: boxel-host-preview.boxel.ai
AWS_REGION: us-east-1
Expand Down
8 changes: 3 additions & 5 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,11 @@ To build the entire repository and run the application, follow these steps:

- Visit SMTP UI at http://localhost:5001/
- Validate email
- Go back to Host and login
- Go back to Host http://localhost:4201/ and login

12. Validate email for login
12. Perform "Setup up Secure Payment Method" flow

- Visit SMTP UI at http://localhost:5001/
- Validate email
- Go back to Host http://localhost:4201/ and login
- More detailed steps can be found in our [README](README.md) Payment Setup section

13. Run ai bot (Optional):

Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ For a quickstart, see [here](./QUICKSTART.md)
- this project uses [volta](https://volta.sh/) for Javascript toolchain version management. Make sure you have the latest verison of volta on your system and have define [the ENV var described here](https://docs.volta.sh/advanced/pnpm).
- this project uses [pnpm](https://pnpm.io/) for package management. run `pnpm install` to install the project dependencies first.
- this project uses [docker](https://docker.com). Make sure to install docker on your system.
- this project uses [stripe-cli](https://stripe.com/docs/stripe-cli) to test payment flows. Make sure to install stripe-cli on your system.
- Ensure that node_modules/.bin is in your path. e.g. include `export PATH="./node_modules/.bin:$PATH"` in your .zshrc

## Orientation
Expand Down Expand Up @@ -229,6 +230,38 @@ In order to run the boxel-motion demo app:
2. `pnpm start`
3. Visit http://localhost:4200 in your browser

## Payment Setup

There is some pre-setup needed to enable free plan on development account:

1. Use stripe cli to listen for the webhooks that Stripe sends to the realm server

```
stripe listen --forward-to localhost:4201/_stripe-webhook --api-key sk_test_api_key_from_the_sandbox_account
```

2. You will get webhook signing secret from stripe cli after Step 1 is done

```
> Ready! You are using Stripe API Version [x]. Your webhook signing secret is whsec_xxxxx
```

3. Go to `packages/realm-server` and run the following command to sync the stripe products to the database, make sure you have the stripe api key set. You only need to run this once OR if you want to sync the products again.

```
STRIPE_API_KEY=... pnpm sync-stripe-products
```

4. Go to `packages/realm-server`, pass STRIPE_WEBHOOK_SECRET & STRIPE_API_KEY environment value and start the realm server. STRIPE_WEBHOOK_SECRET is the value you got from stripe cli in Step 2.

```
STRIPE_WEBHOOK_SECRET=... STRIPE_API_KEY=... pnpm start:all
```

5. Perform "Setup up Secure Payment Method" flow. Subscribe with valid test card [here](https://docs.stripe.com/testing#cards)

You should be able to subscribe successfully after you perform the steps above.

## Running the Tests

There are currently 5 test suites:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
getCurrentActiveSubscription,
getUserByMatrixUserId,
spendCredits,
sumUpCreditsLedger,
} from '@cardstack/billing/billing-queries';
import { PgAdapter, TransactionManager } from '@cardstack/postgres';
import { logger, retry } from '@cardstack/runtime-common';
Expand Down Expand Up @@ -60,6 +61,25 @@ export async function saveUsageCost(
}
}

export async function getAvailableCredits(
pgAdapter: PgAdapter,
matrixUserId: string,
) {
let user = await getUserByMatrixUserId(pgAdapter, matrixUserId);

if (!user) {
throw new Error(
`should not happen: user with matrix id ${matrixUserId} not found in the users table`,
);
}

let availableCredits = await sumUpCreditsLedger(pgAdapter, {
userId: user.id,
});

return availableCredits;
}

async function fetchGenerationCost(generationId: string) {
let response = await (
await fetch(`https://openrouter.ai/api/v1/generation?id=${generationId}`, {
Expand Down
4 changes: 2 additions & 2 deletions packages/ai-bot/lib/matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function getErrorMessage(error: any): string {
return `OpenAI error: ${error.name} - ${error.message}`;
}
if (typeof error === 'string') {
return `Unknown error: ${error}`;
return error;
}
return `Unknown error`;
return 'Unknown error';
}
25 changes: 18 additions & 7 deletions packages/ai-bot/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ import { MatrixClient } from './lib/matrix';
import type { MatrixEvent as DiscreteMatrixEvent } from 'https://cardstack.com/base/matrix-event';
import * as Sentry from '@sentry/node';

import { saveUsageCost } from './lib/ai-cost';
import { getAvailableCredits, saveUsageCost } from './lib/ai-billing';
import { PgAdapter } from '@cardstack/postgres';

let log = logger('ai-bot');

let trackAiUsageCostPromises = new Map<string, Promise<void>>();

const MINIMUM_CREDITS = 10;

class Assistant {
private openai: OpenAI;
private client: MatrixClient;
private pgAdapter: PgAdapter;
pgAdapter: PgAdapter;
id: string;

constructor(client: MatrixClient, id: string) {
Expand Down Expand Up @@ -198,6 +200,12 @@ Common issues are:
}

const responder = new Responder(client, room.roomId);
if (historyError) {
return responder.finalize(
'There was an error processing chat history. Please open another session.',
);
}

await responder.initialize();

// Do not generate new responses if previous ones' cost is still being reported
Expand All @@ -215,11 +223,15 @@ Common issues are:
}
}

if (historyError) {
responder.finalize(
'There was an error processing chat history. Please open another session.',
let availableCredits = await getAvailableCredits(
assistant.pgAdapter,
senderMatrixUserId,
);

if (availableCredits < MINIMUM_CREDITS) {
return responder.onError(
`You need a minimum of ${MINIMUM_CREDITS} credits to continue using the AI bot. Please upgrade to a larger plan, or top up your account.`,
);
return;
}

let generationId: string | undefined;
Expand All @@ -239,7 +251,6 @@ Common issues are:
await responder.onError(error);
});

// We also need to catch the error when getting the final content
let finalContent;
try {
finalContent = await runner.finalContent();
Expand Down
1 change: 1 addition & 0 deletions packages/base/card-api.gts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ export async function flushLogs() {

export class IdentityContext {
readonly identities = new Map<string, CardDef>();
readonly errors = new Set<string>();
}

type JSONAPIResource =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,16 @@ export async function handleCheckoutSessionCompleted(
const matrixUserName = event.data.object.client_reference_id;

if (matrixUserName) {
// The matrix user id was encoded to be alphanumeric by replacing + with - and / with _
// Now we need to reverse that encoding to get back the original base64 string
const base64UserId = matrixUserName.replace(/-/g, '+').replace(/_/g, '/');
const decodedMatrixUserName = Buffer.from(
base64UserId,
'base64',
).toString('utf8');
await updateUserStripeCustomerId(
dbAdapter,
matrixUserName,
decodedMatrixUserName,
stripeCustomerId,
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/boxel-ui/addon/raw-icons/success-bordered.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface Signature {
default: [];
headerIcon: [];
};
Element: HTMLDivElement;
Element: HTMLElement;
}

export default class TabbedHeader extends Component<Signature> {
Expand All @@ -32,6 +32,7 @@ export default class TabbedHeader extends Component<Signature> {
header-background-color=@headerBackgroundColor
header-text-color=(getContrastColor @headerBackgroundColor)
}}
...attributes
>
<div class='app-title-group'>
{{#if (has-block 'headerIcon')}}
Expand Down
4 changes: 2 additions & 2 deletions packages/boxel-ui/addon/src/icons/success-bordered.gts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const IconComponent: TemplateOnlyComponent<Signature> = <template>
height='20'
viewBox='0 0 20 20'
...attributes
><g fill='#37eb77' stroke='rgba(0,0,0,0.1)'><circle
><g fill='var(--icon-fill, #37eb77)' stroke='rgba(0,0,0,0.1)'><circle
cx='10'
cy='10'
r='10'
stroke='none'
/><circle cx='10' cy='10' r='9.5' fill='none' /></g><path
fill='none'
stroke='#000'
stroke='var(--icon-color, #000)'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='2'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": {
"type": "card",
"attributes": {
"name": "Cardstack Studio",
"description": null,
"thumbnailURL": null
},
"meta": {
"adoptsFrom": {
"module": "../crm/contact",
"name": "CompanyCard"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"data": {
"type": "card",
"attributes": {
"name": "David Paul Johnson",
"thumbnailURL": "https://images.pexels.com/photos/4571943/pexels-photo-4571943.jpeg?auto=compress&cs=tinysrgb&w=300&h=300&dpr=1",
"primaryEmail": "[email protected]",
"secondaryEmail": "[email protected]",
"phoneMobile": {
"country": 1,
"area": 415,
"phoneNumber": 1112222
},
"phoneOffice": {
"country": 1,
"area": 415,
"phoneNumber": 2223456
},
"socialLinks": {
"twitterURL": "https://x.com/",
"linkedInURL": ""
},
"status": {
"index": 1,
"label": "Lead"
},
"description": null
},
"relationships": {
"company": {
"links": {
"self": "../CompanyCard/934a7f7b-0a74-4135-95f0-55d965b6c2ab"
}
}
},
"meta": {
"adoptsFrom": {
"module": "../crm/contact",
"name": "Contact"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"data": {
"type": "card",
"attributes": {
"tabs": [
{
"displayName": "Contacts",
"tabId": "Contact",
"ref": {
"name": "Contact",
"module": "crm/contact"
},
"isTable": false
},
{
"displayName": "Deals",
"tabId": "Deal",
"ref": {
"name": "Deal",
"module": "crm/deal"
},
"isTable": false
}
],
"headerIcon": {
"altText": null,
"size": "actual",
"height": null,
"width": null,
"base64": null
},
"title": "Vibeverse",
"description": "Feel the moment",
"thumbnailURL": "https://boxel-images.boxel.ai/icons/vibeverse.jpg"
},
"meta": {
"adoptsFrom": {
"module": "../crm-app",
"name": "CrmApp"
}
}
}
}
Loading

0 comments on commit d17abac

Please sign in to comment.