kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat(cli): WIP improve prompting for version when publishing
rodzic
030200ce91
commit
5d7992e672
|
@ -35,6 +35,11 @@
|
||||||
"format": "uri",
|
"format": "uri",
|
||||||
"description": "Optional URL to the source code of the project (eg, GitHub repo)."
|
"description": "Optional URL to the source code of the project (eg, GitHub repo)."
|
||||||
},
|
},
|
||||||
|
"websiteUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri",
|
||||||
|
"description": "Optional URL to the product's website."
|
||||||
|
},
|
||||||
"origin": {
|
"origin": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { assert, omit, sanitizeSearchParams } from '@agentic/platform-core'
|
import { assert, omit, sanitizeSearchParams } from '@agentic/platform-core'
|
||||||
|
import { ExternalLinkIcon } from 'lucide-react'
|
||||||
|
import Link from 'next/link'
|
||||||
import { useRouter, useSearchParams } from 'next/navigation'
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
|
|
||||||
|
@ -8,6 +10,7 @@ import { useAgentic } from '@/components/agentic-provider'
|
||||||
import { LoadingIndicator } from '@/components/loading-indicator'
|
import { LoadingIndicator } from '@/components/loading-indicator'
|
||||||
import { PageContainer } from '@/components/page-container'
|
import { PageContainer } from '@/components/page-container'
|
||||||
import { ProjectPricingPlans } from '@/components/project-pricing-plans'
|
import { ProjectPricingPlans } from '@/components/project-pricing-plans'
|
||||||
|
import { GitHubIcon } from '@/icons/github'
|
||||||
import { toast, toastError } from '@/lib/notifications'
|
import { toast, toastError } from '@/lib/notifications'
|
||||||
import { useQuery } from '@/lib/query-client'
|
import { useQuery } from '@/lib/query-client'
|
||||||
|
|
||||||
|
@ -148,13 +151,52 @@ export function MarketplaceProjectIndex({
|
||||||
) : !project ? (
|
) : !project ? (
|
||||||
<p>Project "{projectIdentifier}" not found</p>
|
<p>Project "{projectIdentifier}" not found</p>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<div className='flex flex-col'>
|
||||||
<h1
|
<div className='flex flex-col gap-2'>
|
||||||
className='text-center text-balance leading-snug md:leading-none
|
<div className='flex flex-row gap-2.5 items-center'>
|
||||||
text-4xl font-extrabold'
|
<img
|
||||||
>
|
src={
|
||||||
{project.name}
|
project.lastPublishedDeployment?.iconUrl ||
|
||||||
</h1>
|
project.user?.image ||
|
||||||
|
'/agentic-icon-circle-light.svg'
|
||||||
|
}
|
||||||
|
alt={project.name}
|
||||||
|
className='aspect-square w-8 h-8'
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h1 className='font-semibold text-balance text-lg text-gray-900 leading-tight'>
|
||||||
|
{project.name}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex flex-row gap-2.5 items-center'>
|
||||||
|
<div className='text-sm text-gray-500'>
|
||||||
|
{project.identifier}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{project.lastPublishedDeployment?.websiteUrl && (
|
||||||
|
<Link
|
||||||
|
href={project.lastPublishedDeployment.websiteUrl}
|
||||||
|
className='text-sm text-gray-500'
|
||||||
|
>
|
||||||
|
<ExternalLinkIcon />
|
||||||
|
|
||||||
|
<span>Homepage</span>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{project.lastPublishedDeployment?.sourceUrl && (
|
||||||
|
<Link
|
||||||
|
href={project.lastPublishedDeployment.sourceUrl}
|
||||||
|
className='text-sm text-gray-500'
|
||||||
|
>
|
||||||
|
<GitHubIcon />
|
||||||
|
|
||||||
|
<span>GitHub</span>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
<pre className='max-w-lg'>
|
<pre className='max-w-lg'>
|
||||||
|
@ -172,7 +214,7 @@ export function MarketplaceProjectIndex({
|
||||||
isLoadingStripeCheckoutForPlan={isLoadingStripeCheckoutForPlan}
|
isLoadingStripeCheckoutForPlan={isLoadingStripeCheckoutForPlan}
|
||||||
onSubscribe={onSubscribe}
|
onSubscribe={onSubscribe}
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
|
|
|
@ -11,6 +11,9 @@ export default defineConfig({
|
||||||
type: 'mcp',
|
type: 'mcp',
|
||||||
url: process.env.MCP_ORIGIN_URL!
|
url: process.env.MCP_ORIGIN_URL!
|
||||||
},
|
},
|
||||||
|
sourceUrl:
|
||||||
|
'https://github.com/transitive-bullshit/agentic/tree/main/examples/mcp-servers/search',
|
||||||
|
websiteUrl: 'https://agentic.so',
|
||||||
toolConfigs: [
|
toolConfigs: [
|
||||||
{
|
{
|
||||||
name: 'search',
|
name: 'search',
|
||||||
|
|
|
@ -19,7 +19,8 @@ export function registerDeployCommand({
|
||||||
'The directory to load the Agentic project config from (defaults to cwd). This directory must contain an "agentic.config.{ts,js,json}" project file.'
|
'The directory to load the Agentic project config from (defaults to cwd). This directory must contain an "agentic.config.{ts,js,json}" project file.'
|
||||||
)
|
)
|
||||||
.option('-d, --debug', 'Print out the parsed agentic config and return.')
|
.option('-d, --debug', 'Print out the parsed agentic config and return.')
|
||||||
.option('-p, --publish', 'Publishes the deployment after creating it.')
|
// TODO
|
||||||
|
//.option('-p, --publish', 'Publishes the deployment after creating it.')
|
||||||
.action(async (opts) => {
|
.action(async (opts) => {
|
||||||
AuthStore.requireAuth()
|
AuthStore.requireAuth()
|
||||||
|
|
||||||
|
@ -47,12 +48,17 @@ export function registerDeployCommand({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the deployment on the backend, validate it, and optionally
|
// Create the deployment on the backend, validating it in the process.
|
||||||
// publish it.
|
// Note that the backend performs more validation than the client does
|
||||||
|
// and is the ultimate source of truth.
|
||||||
const deployment = await oraPromise(
|
const deployment = await oraPromise(
|
||||||
client.createDeployment(config, {
|
client.createDeployment(
|
||||||
publish: opts.publish ? 'true' : 'false'
|
config
|
||||||
}),
|
// TODO: need to prompt to get or confirm version before publishing
|
||||||
|
// {
|
||||||
|
// publish: opts.publish ? 'true' : 'false'
|
||||||
|
// }
|
||||||
|
),
|
||||||
{
|
{
|
||||||
text: `Creating deployment for project "${config.slug}"`,
|
text: `Creating deployment for project "${config.slug}"`,
|
||||||
successText: `Deployment created successfully`,
|
successText: `Deployment created successfully`,
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { select } from '@clack/prompts'
|
|
||||||
import { Command } from 'commander'
|
import { Command } from 'commander'
|
||||||
import { gracefulExit } from 'exit-hook'
|
import { gracefulExit } from 'exit-hook'
|
||||||
import { oraPromise } from 'ora'
|
import { oraPromise } from 'ora'
|
||||||
import semver from 'semver'
|
|
||||||
|
|
||||||
import type { Context } from '../types'
|
import type { Context } from '../types'
|
||||||
import { AuthStore } from '../lib/auth-store'
|
import { AuthStore } from '../lib/auth-store'
|
||||||
|
import { promptForDeploymentVersion } from '../lib/prompt-for-deployment-version'
|
||||||
import { resolveDeployment } from '../lib/resolve-deployment'
|
import { resolveDeployment } from '../lib/resolve-deployment'
|
||||||
|
|
||||||
export function registerPublishCommand({
|
export function registerPublishCommand({
|
||||||
|
@ -65,39 +64,10 @@ export function registerPublishCommand({
|
||||||
return gracefulExit(1)
|
return gracefulExit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialVersion = deployment.version
|
const version = await promptForDeploymentVersion({
|
||||||
const baseVersion =
|
deployment,
|
||||||
initialVersion || project.lastPublishedDeploymentVersion || '0.0.0'
|
project,
|
||||||
|
logger
|
||||||
const options = [
|
|
||||||
initialVersion
|
|
||||||
? { value: initialVersion, label: initialVersion }
|
|
||||||
: null,
|
|
||||||
{
|
|
||||||
value: semver.inc(baseVersion, 'patch'),
|
|
||||||
label: `${semver.inc(baseVersion, 'patch')} (patch)`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: semver.inc(baseVersion, 'minor'),
|
|
||||||
label: `${semver.inc(baseVersion, 'minor')} (minor)`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: semver.inc(baseVersion, 'major'),
|
|
||||||
label: `${semver.inc(baseVersion, 'major')} (major)`
|
|
||||||
}
|
|
||||||
].filter(Boolean)
|
|
||||||
|
|
||||||
if (project.lastPublishedDeploymentVersion) {
|
|
||||||
logger.info(
|
|
||||||
`Project "${project.identifier}" latest published version is "${project.lastPublishedDeploymentVersion}".\n`
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
logger.info(`Project "${project.identifier}" is not published yet.\n`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = await select({
|
|
||||||
message: `Select version of deployment "${deployment.identifier}" to publish:`,
|
|
||||||
options
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!version || typeof version !== 'string') {
|
if (!version || typeof version !== 'string') {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import type { Deployment, Project } from '@agentic/platform-types'
|
||||||
|
import { select } from '@clack/prompts'
|
||||||
|
import { gracefulExit } from 'exit-hook'
|
||||||
|
import semver from 'semver'
|
||||||
|
|
||||||
|
import type { Context } from '../types'
|
||||||
|
|
||||||
|
export async function promptForDeploymentVersion({
|
||||||
|
deployment,
|
||||||
|
project,
|
||||||
|
logger
|
||||||
|
}: {
|
||||||
|
deployment: Deployment
|
||||||
|
project: Project
|
||||||
|
logger: Context['logger']
|
||||||
|
}): Promise<string | undefined> {
|
||||||
|
const initialVersion = deployment.version
|
||||||
|
const baseVersion =
|
||||||
|
initialVersion || project.lastPublishedDeploymentVersion || '0.0.0'
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
initialVersion ? { value: initialVersion, label: initialVersion } : null,
|
||||||
|
{
|
||||||
|
value: semver.inc(baseVersion, 'patch'),
|
||||||
|
label: `${semver.inc(baseVersion, 'patch')} (patch)`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: semver.inc(baseVersion, 'minor'),
|
||||||
|
label: `${semver.inc(baseVersion, 'minor')} (minor)`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: semver.inc(baseVersion, 'major'),
|
||||||
|
label: `${semver.inc(baseVersion, 'major')} (major)`
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
|
||||||
|
if (project.lastPublishedDeploymentVersion) {
|
||||||
|
logger.info(
|
||||||
|
`Project "${project.identifier}" latest published version is "${project.lastPublishedDeploymentVersion}".\n`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
logger.info(`Project "${project.identifier}" is not published yet.\n`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = await select({
|
||||||
|
message: `Select version of deployment "${deployment.identifier}" to publish:`,
|
||||||
|
options
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!version || typeof version !== 'string') {
|
||||||
|
logger.error('No version selected')
|
||||||
|
gracefulExit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return version
|
||||||
|
}
|
|
@ -768,6 +768,11 @@ export interface components {
|
||||||
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
||||||
*/
|
*/
|
||||||
sourceUrl?: string;
|
sourceUrl?: string;
|
||||||
|
/**
|
||||||
|
* Format: uri
|
||||||
|
* @description Optional URL to the product's website.
|
||||||
|
*/
|
||||||
|
websiteUrl?: string;
|
||||||
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
userId: string;
|
userId: string;
|
||||||
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
@ -1040,6 +1045,11 @@ export interface components {
|
||||||
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
||||||
*/
|
*/
|
||||||
sourceUrl?: string;
|
sourceUrl?: string;
|
||||||
|
/**
|
||||||
|
* Format: uri
|
||||||
|
* @description Optional URL to the product's website.
|
||||||
|
*/
|
||||||
|
websiteUrl?: string;
|
||||||
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
userId: string;
|
userId: string;
|
||||||
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
@ -2409,6 +2419,11 @@ export interface operations {
|
||||||
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
* @description Optional URL to the source code of the project (eg, GitHub repo).
|
||||||
*/
|
*/
|
||||||
sourceUrl?: string;
|
sourceUrl?: string;
|
||||||
|
/**
|
||||||
|
* Format: uri
|
||||||
|
* @description Optional URL to the product's website.
|
||||||
|
*/
|
||||||
|
websiteUrl?: string;
|
||||||
origin: components["schemas"]["OriginAdapterConfig"];
|
origin: components["schemas"]["OriginAdapterConfig"];
|
||||||
/**
|
/**
|
||||||
* @description List of PricingPlans configuring which Stripe subscriptions should be available for the project. Defaults to a single free plan which is useful for developing and testing your project.
|
* @description List of PricingPlans configuring which Stripe subscriptions should be available for the project. Defaults to a single free plan which is useful for developing and testing your project.
|
||||||
|
|
|
@ -38,11 +38,14 @@ export type Consumer = Simplify<
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
export type Project = Simplify<
|
export type Project = Simplify<
|
||||||
components['schemas']['Project'] & {
|
Omit<
|
||||||
|
components['schemas']['Project'],
|
||||||
|
'lastPublishedDeployment' | 'lastDeployment'
|
||||||
|
> & {
|
||||||
user?: User
|
user?: User
|
||||||
team?: Team
|
team?: Team
|
||||||
lastPublishedDeployment?: Deployment
|
lastPublishedDeployment?: Simplify<Omit<Deployment, 'project'>>
|
||||||
lastDeployment?: Deployment
|
lastDeployment?: Simplify<Omit<Deployment, 'project'>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The public base HTTP URL for the project supporting HTTP POST requests for
|
* The public base HTTP URL for the project supporting HTTP POST requests for
|
||||||
|
@ -78,12 +81,14 @@ export type Project = Simplify<
|
||||||
export type Deployment = Simplify<
|
export type Deployment = Simplify<
|
||||||
Omit<
|
Omit<
|
||||||
components['schemas']['Deployment'],
|
components['schemas']['Deployment'],
|
||||||
'pricingPlans' | 'toolConfigs' | 'defaultRateLimit'
|
'pricingPlans' | 'toolConfigs' | 'defaultRateLimit' | 'project'
|
||||||
> & {
|
> & {
|
||||||
pricingPlans: PricingPlan[]
|
pricingPlans: PricingPlan[]
|
||||||
toolConfigs: ToolConfig[]
|
toolConfigs: ToolConfig[]
|
||||||
defaultRateLimit: RateLimit
|
defaultRateLimit: RateLimit
|
||||||
project?: components['schemas']['Project']
|
project?: Simplify<
|
||||||
|
Omit<Project, 'lastPublishedDeployment' | 'lastDeployment'>
|
||||||
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The public base HTTP URL for the deployment supporting HTTP POST requests
|
* The public base HTTP URL for the deployment supporting HTTP POST requests
|
||||||
|
@ -123,16 +128,19 @@ export type Deployment = Simplify<
|
||||||
export type AdminDeployment = Simplify<
|
export type AdminDeployment = Simplify<
|
||||||
Omit<
|
Omit<
|
||||||
components['schemas']['AdminDeployment'],
|
components['schemas']['AdminDeployment'],
|
||||||
'pricingPlans' | 'toolConfigs' | 'defaultRateLimit' | 'origin'
|
'pricingPlans' | 'toolConfigs' | 'defaultRateLimit' | 'origin' | 'project'
|
||||||
> & {
|
> & {
|
||||||
pricingPlans: PricingPlan[]
|
pricingPlans: PricingPlan[]
|
||||||
toolConfigs: ToolConfig[]
|
toolConfigs: ToolConfig[]
|
||||||
defaultRateLimit: RateLimit
|
defaultRateLimit: RateLimit
|
||||||
origin: OriginAdapter
|
origin: OriginAdapter
|
||||||
project?: components['schemas']['Project']
|
|
||||||
} & Pick<
|
} & Pick<
|
||||||
Deployment,
|
Deployment,
|
||||||
'gatewayBaseUrl' | 'gatewayMcpUrl' | 'marketplaceUrl' | 'adminUrl'
|
| 'gatewayBaseUrl'
|
||||||
|
| 'gatewayMcpUrl'
|
||||||
|
| 'marketplaceUrl'
|
||||||
|
| 'adminUrl'
|
||||||
|
| 'project'
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
2
todo.md
2
todo.md
|
@ -53,7 +53,7 @@
|
||||||
- stripe
|
- stripe
|
||||||
- re-add coupons
|
- re-add coupons
|
||||||
- declarative json-based pricing
|
- declarative json-based pricing
|
||||||
- like https://github.com/tierrun/tier and Saasify
|
- like Saasify and https://github.com/tierrun/tier
|
||||||
- https://github.com/tierrun/tier/blob/main/pricing/schema.json
|
- https://github.com/tierrun/tier/blob/main/pricing/schema.json
|
||||||
- https://blog.tier.run/tier-hello-world-demo
|
- https://blog.tier.run/tier-hello-world-demo
|
||||||
- stripe connect
|
- stripe connect
|
||||||
|
|
Ładowanie…
Reference in New Issue