kenobi-pages 0.1.2 → 0.1.4
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/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.js +0 -0
- package/package.json +8 -3
- package/src/build.ts +0 -50
- package/src/cli.ts +0 -472
- package/src/client.ts +0 -127
- package/src/errors.ts +0 -25
- package/src/index.ts +0 -18
- package/src/types.ts +0 -132
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var l=Object.defineProperty;var o=(n,s)=>l(n,"name",{value:s,configurable:!0});import{KenobiPagesError as m,KenobiNotFoundError as p,KenobiUnauthorizedError as b}from"./errors";const d="https://kenobi.ai",t=o(async(n,s,e)=>{const i=`${(n.baseUrl??d).replace(/\/+$/,"")}${s}`,u={"x-kenobi-key":n.apiKey,"Content-Type":"application/json"},c={method:e?.method??"GET",headers:u};e?.body!==void 0&&(c.body=JSON.stringify(e.body)),(e?.revalidate!==void 0||e?.tags)&&(c.next={},e.revalidate!==void 0&&(c.next.revalidate=e.revalidate),e.tags&&(c.next.tags=[...e.tags]));const a=await fetch(i,c);if(a.ok)return a;if(a.status===401)throw new b;if(a.status===404)throw new p;const w=await a.text().catch(()=>"Unknown error");throw new m(`Kenobi API error (${a.status}): ${w}`,a.status,"API_ERROR")},"fetchFromKenobi"),f=o(n=>({getPage:o(async(s,e,r)=>{try{return await(await t(n,`/api/v1/pages/${s}/${e}`,r)).json()}catch(i){if(i instanceof p)return null;throw i}},"getPage"),getSchema:o(async(s,e)=>await(await t(n,`/api/v1/pages/${s}/schema`,e)).json(),"getSchema"),postSchema:o(async(s,e)=>await(await t(n,"/api/v1/pages/schema",{method:"POST",body:{name:s,schema:e}})).json(),"postSchema"),listWorkflows:o(async()=>(await(await t(n,"/api/v1/workflows")).json()).workflows,"listWorkflows"),getWorkflow:o(async s=>await(await t(n,`/api/v1/workflows/${s}`)).json(),"getWorkflow"),triggerRun:o(async(s,e)=>await(await t(n,`/api/v1/workflows/${s}/run`,{method:"POST",body:{params:e}})).json(),"triggerRun"),getRunStatus:o(async(s,e)=>await(await t(n,`/api/v1/workflows/${s}/runs/${e}`)).json(),"getRunStatus")}),"createKenobiPagesClient");export{f as createKenobiPagesClient};
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class KenobiPagesError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly code: string;
|
|
4
|
+
constructor(message: string, status: number, code: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class KenobiNotFoundError extends KenobiPagesError {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class KenobiUnauthorizedError extends KenobiPagesError {
|
|
10
|
+
constructor(message?: string);
|
|
11
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var u=Object.defineProperty;var e=(o,r)=>u(o,"name",{value:r,configurable:!0});class s extends Error{static{e(this,"KenobiPagesError")}status;code;constructor(r,t,n){super(r),this.name="KenobiPagesError",this.status=t,this.code=n}}class a extends s{static{e(this,"KenobiNotFoundError")}constructor(r="Resource not found"){super(r,404,"NOT_FOUND"),this.name="KenobiNotFoundError"}}class c extends s{static{e(this,"KenobiUnauthorizedError")}constructor(r="Unauthorized \u2014 check your API key"){super(r,401,"UNAUTHORIZED"),this.name="KenobiUnauthorizedError"}}export{a as KenobiNotFoundError,s as KenobiPagesError,c as KenobiUnauthorizedError};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createKenobiPagesClient } from "./client";
|
|
2
|
+
export { KenobiPagesError, KenobiNotFoundError, KenobiUnauthorizedError } from "./errors";
|
|
3
|
+
export type { KenobiPagesClient, KenobiPagesConfig, KenobiFetchOptions, KenobiPageResponse, KenobiPageSchema, KenobiSchemaResponse, OutputFieldSpec, PostSchemaResponse, RunHandle, RunStatus, RunStatusResponse, WorkflowDetail, WorkflowParam, WorkflowSummary, } from "./types";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createKenobiPagesClient as n}from"./client";import{KenobiPagesError as t,KenobiNotFoundError as a,KenobiUnauthorizedError as i}from"./errors";export{a as KenobiNotFoundError,t as KenobiPagesError,i as KenobiUnauthorizedError,n as createKenobiPagesClient};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface KenobiPagesConfig {
|
|
2
|
+
/** Org-scoped public key from the Kenobi workflow builder (pk_live_... or pk_test_...). */
|
|
3
|
+
readonly apiKey: string;
|
|
4
|
+
/** Base URL of the Kenobi API. Defaults to https://kenobi.ai */
|
|
5
|
+
readonly baseUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface KenobiFetchOptions {
|
|
8
|
+
/** Next.js ISR revalidation interval in seconds, or `false` to disable caching. */
|
|
9
|
+
readonly revalidate?: number | false;
|
|
10
|
+
/** Next.js cache tags for on-demand revalidation via `revalidateTag()`. */
|
|
11
|
+
readonly tags?: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export interface KenobiPageResponse {
|
|
14
|
+
readonly content: Record<string, unknown>;
|
|
15
|
+
readonly metadata: Record<string, unknown> | null;
|
|
16
|
+
readonly updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface KenobiSchemaResponse {
|
|
19
|
+
readonly schema: Record<string, unknown>;
|
|
20
|
+
readonly provider: string;
|
|
21
|
+
readonly title: string;
|
|
22
|
+
}
|
|
23
|
+
export interface PostSchemaResponse {
|
|
24
|
+
readonly sourceKey: string;
|
|
25
|
+
readonly name: string;
|
|
26
|
+
}
|
|
27
|
+
interface FieldSpecBase {
|
|
28
|
+
readonly description?: string;
|
|
29
|
+
readonly optional?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export type OutputFieldSpec = ({
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
readonly min?: number;
|
|
34
|
+
readonly max?: number;
|
|
35
|
+
} & FieldSpecBase) | ({
|
|
36
|
+
readonly type: "url";
|
|
37
|
+
} & FieldSpecBase) | ({
|
|
38
|
+
readonly type: "number";
|
|
39
|
+
readonly min?: number;
|
|
40
|
+
readonly max?: number;
|
|
41
|
+
readonly integer?: boolean;
|
|
42
|
+
} & FieldSpecBase) | ({
|
|
43
|
+
readonly type: "boolean";
|
|
44
|
+
} & FieldSpecBase) | ({
|
|
45
|
+
readonly type: "enum";
|
|
46
|
+
readonly values?: readonly string[];
|
|
47
|
+
} & FieldSpecBase) | ({
|
|
48
|
+
readonly type: "object";
|
|
49
|
+
readonly fields: Readonly<Record<string, OutputFieldSpec>>;
|
|
50
|
+
} & FieldSpecBase) | ({
|
|
51
|
+
readonly type: "array";
|
|
52
|
+
readonly items: OutputFieldSpec;
|
|
53
|
+
readonly min?: number;
|
|
54
|
+
readonly max?: number;
|
|
55
|
+
} & FieldSpecBase);
|
|
56
|
+
export interface KenobiPageSchema {
|
|
57
|
+
readonly fields: Readonly<Record<string, OutputFieldSpec>>;
|
|
58
|
+
}
|
|
59
|
+
export interface WorkflowParam {
|
|
60
|
+
readonly name: string;
|
|
61
|
+
readonly description?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface WorkflowSummary {
|
|
64
|
+
readonly id: number;
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly slug: string;
|
|
67
|
+
readonly params: readonly WorkflowParam[];
|
|
68
|
+
readonly outputProvider: string | null;
|
|
69
|
+
readonly outputTitle: string | null;
|
|
70
|
+
}
|
|
71
|
+
export interface WorkflowDetail {
|
|
72
|
+
readonly id: number;
|
|
73
|
+
readonly name: string;
|
|
74
|
+
readonly slug: string;
|
|
75
|
+
readonly params: readonly WorkflowParam[];
|
|
76
|
+
readonly output: {
|
|
77
|
+
readonly provider: string | null;
|
|
78
|
+
readonly title: string | null;
|
|
79
|
+
readonly schema: Record<string, unknown> | null;
|
|
80
|
+
};
|
|
81
|
+
readonly destinations: readonly {
|
|
82
|
+
readonly adapter: string;
|
|
83
|
+
}[];
|
|
84
|
+
}
|
|
85
|
+
export interface RunHandle {
|
|
86
|
+
readonly runId: string;
|
|
87
|
+
readonly status: string;
|
|
88
|
+
}
|
|
89
|
+
export type RunStatus = "QUEUED" | "EXECUTING" | "COMPLETED" | "FAILED" | "CANCELED";
|
|
90
|
+
export interface RunStatusResponse {
|
|
91
|
+
readonly runId: string;
|
|
92
|
+
readonly status: RunStatus;
|
|
93
|
+
readonly output: Record<string, unknown> | null;
|
|
94
|
+
readonly createdAt: string;
|
|
95
|
+
readonly finishedAt: string | null;
|
|
96
|
+
}
|
|
97
|
+
export interface KenobiPagesClient {
|
|
98
|
+
readonly getPage: (workflowId: number, slug: string, opts?: KenobiFetchOptions) => Promise<KenobiPageResponse | null>;
|
|
99
|
+
readonly getSchema: (workflowId: number, opts?: KenobiFetchOptions) => Promise<KenobiSchemaResponse>;
|
|
100
|
+
readonly postSchema: (name: string, schema: KenobiPageSchema) => Promise<PostSchemaResponse>;
|
|
101
|
+
readonly listWorkflows: () => Promise<readonly WorkflowSummary[]>;
|
|
102
|
+
readonly getWorkflow: (workflowId: number) => Promise<WorkflowDetail>;
|
|
103
|
+
readonly triggerRun: (workflowId: number, params: Record<string, string>) => Promise<RunHandle>;
|
|
104
|
+
readonly getRunStatus: (workflowId: number, runId: string) => Promise<RunStatusResponse>;
|
|
105
|
+
}
|
|
106
|
+
export {};
|
package/dist/types.js
ADDED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kenobi-pages",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Kenobi Pages SDK — fetch personalized page content from Kenobi workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
|
-
".":
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
8
11
|
},
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"main": "./dist/index.js",
|
|
9
14
|
"bin": {
|
|
10
15
|
"kenobi-pages": "./bin/cli.mjs"
|
|
11
16
|
},
|
|
12
17
|
"files": [
|
|
13
18
|
"bin",
|
|
14
|
-
"
|
|
19
|
+
"dist"
|
|
15
20
|
],
|
|
16
21
|
"publishConfig": {
|
|
17
22
|
"access": "public"
|
package/src/build.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
|
|
3
|
-
import * as fs from "fs"
|
|
4
|
-
import * as path from "path"
|
|
5
|
-
|
|
6
|
-
import * as esbuild from "esbuild"
|
|
7
|
-
|
|
8
|
-
const isProd =
|
|
9
|
-
process.argv.includes("--prod") || process.env.NODE_ENV === "production"
|
|
10
|
-
|
|
11
|
-
const packageJsonPath = path.join(process.cwd(), "package.json")
|
|
12
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
|
|
13
|
-
const version = packageJson.version as string
|
|
14
|
-
|
|
15
|
-
const entryFile = path.join(process.cwd(), "src", "cli.ts")
|
|
16
|
-
const outFile = path.join(process.cwd(), "bin", "cli.mjs")
|
|
17
|
-
|
|
18
|
-
const build = async () => {
|
|
19
|
-
console.log(
|
|
20
|
-
`📦 Building CLI ${isProd ? "(production)" : "(development)"} v${version}...`
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
const result = await esbuild.build({
|
|
24
|
-
entryPoints: [entryFile],
|
|
25
|
-
bundle: true,
|
|
26
|
-
platform: "node",
|
|
27
|
-
target: ["node18"],
|
|
28
|
-
format: "esm",
|
|
29
|
-
treeShaking: true,
|
|
30
|
-
minify: isProd,
|
|
31
|
-
keepNames: true,
|
|
32
|
-
metafile: true,
|
|
33
|
-
logLevel: "info",
|
|
34
|
-
outfile: outFile,
|
|
35
|
-
banner: {
|
|
36
|
-
js: "#!/usr/bin/env node",
|
|
37
|
-
},
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
if (result.metafile) {
|
|
41
|
-
const outputs = Object.values(result.metafile.outputs)
|
|
42
|
-
const totalSize = outputs.reduce((acc, output) => acc + output.bytes, 0)
|
|
43
|
-
console.log(`\n✅ Build complete: ${(totalSize / 1024).toFixed(2)} KB → ${outFile}`)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
build().catch((error) => {
|
|
48
|
-
console.error("Build failed:", error)
|
|
49
|
-
process.exit(1)
|
|
50
|
-
})
|
package/src/cli.ts
DELETED
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
readFileSync,
|
|
5
|
-
writeFileSync,
|
|
6
|
-
appendFileSync,
|
|
7
|
-
} from "node:fs"
|
|
8
|
-
import { readFile } from "node:fs/promises"
|
|
9
|
-
import { homedir } from "node:os"
|
|
10
|
-
import { join, resolve } from "node:path"
|
|
11
|
-
import { createInterface } from "node:readline"
|
|
12
|
-
|
|
13
|
-
const DEFAULT_BASE_URL = "https://kenobi.ai"
|
|
14
|
-
const GLOBAL_CONFIG_DIR = join(homedir(), ".kenobi")
|
|
15
|
-
const GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, "config.json")
|
|
16
|
-
const ENV_VAR_NAME = "KENOBI_PAGES_KEY"
|
|
17
|
-
|
|
18
|
-
// ── Types ──
|
|
19
|
-
|
|
20
|
-
interface GlobalConfig {
|
|
21
|
-
apiKey?: string
|
|
22
|
-
baseUrl?: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface FetchOptions {
|
|
26
|
-
method?: string
|
|
27
|
-
body?: Record<string, unknown>
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface OutputFieldSpec {
|
|
31
|
-
type: string
|
|
32
|
-
optional?: boolean
|
|
33
|
-
description?: string
|
|
34
|
-
values?: string[]
|
|
35
|
-
fields?: Record<string, OutputFieldSpec>
|
|
36
|
-
items?: OutputFieldSpec
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// ── Global config ──
|
|
40
|
-
|
|
41
|
-
const readGlobalConfig = (): GlobalConfig => {
|
|
42
|
-
try {
|
|
43
|
-
return JSON.parse(readFileSync(GLOBAL_CONFIG_PATH, "utf-8")) as GlobalConfig
|
|
44
|
-
} catch {
|
|
45
|
-
return {}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const writeGlobalConfig = (config: GlobalConfig) => {
|
|
50
|
-
mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true })
|
|
51
|
-
writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n")
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ── Helpers ──
|
|
55
|
-
|
|
56
|
-
const getApiKey = (): string => {
|
|
57
|
-
const key = process.env[ENV_VAR_NAME] || readGlobalConfig().apiKey
|
|
58
|
-
if (!key) {
|
|
59
|
-
console.error("Error: No API key found.")
|
|
60
|
-
console.error("")
|
|
61
|
-
console.error("Run 'npx kenobi-pages init' to set up your API key.")
|
|
62
|
-
console.error("")
|
|
63
|
-
console.error("Or set the KENOBI_PAGES_KEY environment variable directly.")
|
|
64
|
-
process.exit(1)
|
|
65
|
-
}
|
|
66
|
-
return key
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const getBaseUrl = (): string =>
|
|
70
|
-
(
|
|
71
|
-
process.env.KENOBI_BASE_URL ??
|
|
72
|
-
readGlobalConfig().baseUrl ??
|
|
73
|
-
DEFAULT_BASE_URL
|
|
74
|
-
).replace(/\/+$/, "")
|
|
75
|
-
|
|
76
|
-
const fetchKenobi = async (path: string, opts: FetchOptions = {}) => {
|
|
77
|
-
const url = `${getBaseUrl()}${path}`
|
|
78
|
-
const res = await fetch(url, {
|
|
79
|
-
method: opts.method ?? "GET",
|
|
80
|
-
headers: {
|
|
81
|
-
"x-kenobi-key": getApiKey(),
|
|
82
|
-
"Content-Type": "application/json",
|
|
83
|
-
},
|
|
84
|
-
body: opts.body ? JSON.stringify(opts.body) : undefined,
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
if (!res.ok) {
|
|
88
|
-
const text = await res.text().catch(() => "Unknown error")
|
|
89
|
-
const exitCode =
|
|
90
|
-
res.status === 401 || res.status === 403
|
|
91
|
-
? 4
|
|
92
|
-
: res.status === 404
|
|
93
|
-
? 3
|
|
94
|
-
: 1
|
|
95
|
-
console.error(`Error ${res.status}: ${text}`)
|
|
96
|
-
process.exit(exitCode)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return res.json()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const prompt = (question: string): Promise<string> =>
|
|
103
|
-
new Promise((resolve) => {
|
|
104
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr })
|
|
105
|
-
rl.question(question, (answer) => {
|
|
106
|
-
rl.close()
|
|
107
|
-
resolve(answer.trim())
|
|
108
|
-
})
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
const readStdin = (): Promise<string> =>
|
|
112
|
-
new Promise((resolve, reject) => {
|
|
113
|
-
let data = ""
|
|
114
|
-
process.stdin.setEncoding("utf-8")
|
|
115
|
-
process.stdin.on("data", (chunk: string) => {
|
|
116
|
-
data += chunk
|
|
117
|
-
})
|
|
118
|
-
process.stdin.on("end", () => resolve(data))
|
|
119
|
-
process.stdin.on("error", reject)
|
|
120
|
-
if (process.stdin.isTTY) resolve("")
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
const parseFileArg = async (args: string[]): Promise<string | null> => {
|
|
124
|
-
const fileIdx = args.indexOf("--file")
|
|
125
|
-
if (fileIdx !== -1 && args[fileIdx + 1]) {
|
|
126
|
-
return readFile(args[fileIdx + 1], "utf-8")
|
|
127
|
-
}
|
|
128
|
-
return null
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ── Init ──
|
|
132
|
-
|
|
133
|
-
const initCommand = async () => {
|
|
134
|
-
console.error("Kenobi Pages — Setup")
|
|
135
|
-
console.error("")
|
|
136
|
-
console.error("Find your Pages API key in the workflow builder:")
|
|
137
|
-
console.error(" https://kenobi.ai/testing/cortex")
|
|
138
|
-
console.error("")
|
|
139
|
-
|
|
140
|
-
const key = await prompt("Paste your API key (pk_live_... or pk_test_...): ")
|
|
141
|
-
|
|
142
|
-
if (!key) {
|
|
143
|
-
console.error("No key provided. Aborting.")
|
|
144
|
-
process.exit(1)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (!key.startsWith("pk_live_") && !key.startsWith("pk_test_")) {
|
|
148
|
-
console.error(
|
|
149
|
-
`Warning: "${key}" doesn't look like a Kenobi public key (expected pk_live_... or pk_test_...).`
|
|
150
|
-
)
|
|
151
|
-
const proceed = await prompt("Continue anyway? (y/N): ")
|
|
152
|
-
if (proceed.toLowerCase() !== "y") {
|
|
153
|
-
console.error("Aborting.")
|
|
154
|
-
process.exit(1)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const config = readGlobalConfig()
|
|
159
|
-
config.apiKey = key
|
|
160
|
-
writeGlobalConfig(config)
|
|
161
|
-
console.error(`✓ Saved to ${GLOBAL_CONFIG_PATH}`)
|
|
162
|
-
|
|
163
|
-
const envLocalPath = resolve(process.cwd(), ".env.local")
|
|
164
|
-
const envPath = resolve(process.cwd(), ".env")
|
|
165
|
-
const targetEnvFile = existsSync(envLocalPath)
|
|
166
|
-
? envLocalPath
|
|
167
|
-
: existsSync(envPath)
|
|
168
|
-
? envPath
|
|
169
|
-
: null
|
|
170
|
-
|
|
171
|
-
if (targetEnvFile) {
|
|
172
|
-
const contents = readFileSync(targetEnvFile, "utf-8")
|
|
173
|
-
if (contents.includes(ENV_VAR_NAME)) {
|
|
174
|
-
console.error(
|
|
175
|
-
`✓ ${ENV_VAR_NAME} already present in ${targetEnvFile.split("/").pop()}`
|
|
176
|
-
)
|
|
177
|
-
} else {
|
|
178
|
-
const suffix = contents.endsWith("\n") ? "" : "\n"
|
|
179
|
-
appendFileSync(targetEnvFile, `${suffix}${ENV_VAR_NAME}="${key}"\n`)
|
|
180
|
-
console.error(
|
|
181
|
-
`✓ Added ${ENV_VAR_NAME} to ${targetEnvFile.split("/").pop()}`
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
} else {
|
|
185
|
-
const createEnvLocal = await prompt(
|
|
186
|
-
"No .env.local found. Create one with your API key? (Y/n): "
|
|
187
|
-
)
|
|
188
|
-
if (createEnvLocal.toLowerCase() !== "n") {
|
|
189
|
-
writeFileSync(envLocalPath, `${ENV_VAR_NAME}="${key}"\n`)
|
|
190
|
-
console.error(`✓ Created .env.local with ${ENV_VAR_NAME}`)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
console.error("")
|
|
195
|
-
console.error("Done! You can now use kenobi-pages commands.")
|
|
196
|
-
console.error(
|
|
197
|
-
' npx kenobi-pages schema push "My Page" \'{"fields":{...}}\''
|
|
198
|
-
)
|
|
199
|
-
console.error(" npx kenobi-pages types <workflowId>")
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// ── Subcommands ──
|
|
203
|
-
|
|
204
|
-
const schemaGet = async (args: string[]) => {
|
|
205
|
-
const workflowId = args[0]
|
|
206
|
-
if (!workflowId) {
|
|
207
|
-
console.error("Usage: kenobi-pages schema get <workflowId>")
|
|
208
|
-
process.exit(2)
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const data = await fetchKenobi(`/api/v1/pages/${workflowId}/schema`)
|
|
212
|
-
console.log(JSON.stringify(data, null, 2))
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const schemaPush = async (args: string[]) => {
|
|
216
|
-
const name = args[0]
|
|
217
|
-
if (!name) {
|
|
218
|
-
console.error("Usage: kenobi-pages schema push <name> '<json>'")
|
|
219
|
-
console.error(" kenobi-pages schema push <name> --file schema.json")
|
|
220
|
-
console.error(" echo '<json>' | kenobi-pages schema push <name>")
|
|
221
|
-
process.exit(2)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const remaining = args.slice(1)
|
|
225
|
-
const fileContent = await parseFileArg(remaining)
|
|
226
|
-
|
|
227
|
-
const inlineArg = !fileContent
|
|
228
|
-
? remaining.find((a) => a.startsWith("{"))
|
|
229
|
-
: null
|
|
230
|
-
const stdinContent = !fileContent && !inlineArg ? await readStdin() : null
|
|
231
|
-
const rawJson = fileContent ?? inlineArg ?? stdinContent
|
|
232
|
-
|
|
233
|
-
if (!rawJson || rawJson.trim().length === 0) {
|
|
234
|
-
console.error("Error: No schema provided.")
|
|
235
|
-
console.error("Pass inline JSON, --file <path>, or pipe to stdin.")
|
|
236
|
-
process.exit(2)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
let schema: Record<string, unknown>
|
|
240
|
-
try {
|
|
241
|
-
schema = JSON.parse(rawJson) as Record<string, unknown>
|
|
242
|
-
} catch {
|
|
243
|
-
console.error("Error: Invalid JSON.")
|
|
244
|
-
process.exit(2)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const data = (await fetchKenobi("/api/v1/pages/schema", {
|
|
248
|
-
method: "POST",
|
|
249
|
-
body: { name, schema },
|
|
250
|
-
})) as { name: string; sourceKey: string }
|
|
251
|
-
|
|
252
|
-
console.log(JSON.stringify(data, null, 2))
|
|
253
|
-
console.error(`Schema "${data.name}" pushed successfully.`)
|
|
254
|
-
console.error(`Source key: ${data.sourceKey}`)
|
|
255
|
-
console.error(
|
|
256
|
-
"You can now select this schema as an output target in the Kenobi workflow builder."
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const pageGet = async (args: string[]) => {
|
|
261
|
-
const [workflowId, slug] = args
|
|
262
|
-
if (!workflowId || !slug) {
|
|
263
|
-
console.error("Usage: kenobi-pages page get <workflowId> <slug>")
|
|
264
|
-
process.exit(2)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const data = await fetchKenobi(`/api/v1/pages/${workflowId}/${slug}`)
|
|
268
|
-
console.log(JSON.stringify(data, null, 2))
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const typesGen = async (args: string[]) => {
|
|
272
|
-
const workflowId = args[0]
|
|
273
|
-
if (!workflowId) {
|
|
274
|
-
console.error("Usage: kenobi-pages types <workflowId>")
|
|
275
|
-
process.exit(2)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const data = (await fetchKenobi(
|
|
279
|
-
`/api/v1/pages/${workflowId}/schema`
|
|
280
|
-
)) as { schema: { fields?: Record<string, OutputFieldSpec> }; title?: string }
|
|
281
|
-
const schema = data.schema
|
|
282
|
-
|
|
283
|
-
if (!schema?.fields) {
|
|
284
|
-
console.error("Error: Workflow has no output schema with fields.")
|
|
285
|
-
process.exit(1)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const indent = (level: number) => " ".repeat(level)
|
|
289
|
-
|
|
290
|
-
const fieldToTs = (spec: OutputFieldSpec, level = 1): string => {
|
|
291
|
-
switch (spec.type) {
|
|
292
|
-
case "string":
|
|
293
|
-
case "url":
|
|
294
|
-
return "string"
|
|
295
|
-
case "number":
|
|
296
|
-
return "number"
|
|
297
|
-
case "boolean":
|
|
298
|
-
return "boolean"
|
|
299
|
-
case "enum":
|
|
300
|
-
return spec.values?.length
|
|
301
|
-
? spec.values.map((v) => `"${v}"`).join(" | ")
|
|
302
|
-
: "string"
|
|
303
|
-
case "object": {
|
|
304
|
-
const entries = Object.entries(spec.fields ?? {})
|
|
305
|
-
if (entries.length === 0) return "Record<string, unknown>"
|
|
306
|
-
const lines = entries.map(([k, v]) => {
|
|
307
|
-
const opt = v.optional ? "?" : ""
|
|
308
|
-
return `${indent(level)}${k}${opt}: ${fieldToTs(v, level + 1)}`
|
|
309
|
-
})
|
|
310
|
-
return `{\n${lines.join("\n")}\n${indent(level - 1)}}`
|
|
311
|
-
}
|
|
312
|
-
case "array":
|
|
313
|
-
return `Array<${fieldToTs(spec.items!, level)}>`
|
|
314
|
-
default:
|
|
315
|
-
return "unknown"
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const entries = Object.entries(schema.fields)
|
|
320
|
-
const lines = entries.map(([k, v]) => {
|
|
321
|
-
const opt = v.optional ? "?" : ""
|
|
322
|
-
const comment = v.description ? ` /** ${v.description} */\n` : ""
|
|
323
|
-
return `${comment} ${k}${opt}: ${fieldToTs(v, 2)}`
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
const typeName = data.title
|
|
327
|
-
? data.title.replace(/[^a-zA-Z0-9]+/g, "")
|
|
328
|
-
: "PageContent"
|
|
329
|
-
|
|
330
|
-
const output = `export interface ${typeName} {\n${lines.join("\n")}\n}\n`
|
|
331
|
-
console.log(output)
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// ── Run workflow ──
|
|
335
|
-
|
|
336
|
-
const TERMINAL_STATUSES = new Set(["COMPLETED", "FAILED", "CANCELED", "SYSTEM_FAILURE", "CRASHED"])
|
|
337
|
-
|
|
338
|
-
const sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))
|
|
339
|
-
|
|
340
|
-
const runWorkflow = async (args: string[]) => {
|
|
341
|
-
const workflowId = args[0]
|
|
342
|
-
if (!workflowId) {
|
|
343
|
-
console.error("Usage: kenobi-pages run <workflowId> [--params '<json>']")
|
|
344
|
-
process.exit(2)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const remaining = args.slice(1)
|
|
348
|
-
const paramsIdx = remaining.indexOf("--params")
|
|
349
|
-
let params: Record<string, string> = {}
|
|
350
|
-
if (paramsIdx !== -1 && remaining[paramsIdx + 1]) {
|
|
351
|
-
try {
|
|
352
|
-
params = JSON.parse(remaining[paramsIdx + 1]) as Record<string, string>
|
|
353
|
-
} catch {
|
|
354
|
-
console.error("Error: Invalid JSON in --params")
|
|
355
|
-
process.exit(2)
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const handle = (await fetchKenobi(`/api/v1/workflows/${workflowId}/run`, {
|
|
360
|
-
method: "POST",
|
|
361
|
-
body: { params },
|
|
362
|
-
})) as { runId: string; status: string }
|
|
363
|
-
|
|
364
|
-
console.error(`Run triggered: ${handle.runId}`)
|
|
365
|
-
console.error("Polling for completion...")
|
|
366
|
-
|
|
367
|
-
let delay = 2000
|
|
368
|
-
const MAX_DELAY = 15000
|
|
369
|
-
|
|
370
|
-
// eslint-disable-next-line no-constant-condition
|
|
371
|
-
while (true) {
|
|
372
|
-
await sleep(delay)
|
|
373
|
-
const status = (await fetchKenobi(
|
|
374
|
-
`/api/v1/workflows/${workflowId}/runs/${handle.runId}`
|
|
375
|
-
)) as { runId: string; status: string; output?: unknown; finishedAt?: string }
|
|
376
|
-
|
|
377
|
-
console.error(` Status: ${status.status}`)
|
|
378
|
-
|
|
379
|
-
if (TERMINAL_STATUSES.has(status.status)) {
|
|
380
|
-
console.log(JSON.stringify(status, null, 2))
|
|
381
|
-
if (status.status !== "COMPLETED") process.exit(1)
|
|
382
|
-
return
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
delay = Math.min(delay * 1.5, MAX_DELAY)
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const listWorkflows = async () => {
|
|
390
|
-
const data = (await fetchKenobi("/api/v1/workflows")) as {
|
|
391
|
-
workflows: Array<{
|
|
392
|
-
id: number
|
|
393
|
-
name: string
|
|
394
|
-
slug: string
|
|
395
|
-
params: Array<{ name: string; description?: string }>
|
|
396
|
-
}>
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
console.log(JSON.stringify(data, null, 2))
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// ── Router ──
|
|
403
|
-
|
|
404
|
-
const HELP = `kenobi-pages — Kenobi Pages CLI
|
|
405
|
-
|
|
406
|
-
Commands:
|
|
407
|
-
kenobi-pages init Set up your API key (interactive)
|
|
408
|
-
kenobi-pages schema get <workflowId> Fetch a workflow's output schema
|
|
409
|
-
kenobi-pages schema push <name> '<json>' Push a schema to Kenobi (inline JSON)
|
|
410
|
-
kenobi-pages schema push <name> --file f Push a schema to Kenobi (from file)
|
|
411
|
-
kenobi-pages page get <workflowId> <slug> Fetch page content for a specific lead
|
|
412
|
-
kenobi-pages types <workflowId> Generate TypeScript interface from schema
|
|
413
|
-
kenobi-pages workflows List workflows for your org
|
|
414
|
-
kenobi-pages run <workflowId> [--params '{}'] Trigger a workflow run and poll to completion
|
|
415
|
-
|
|
416
|
-
Examples:
|
|
417
|
-
npx kenobi-pages init
|
|
418
|
-
npx kenobi-pages schema get 42
|
|
419
|
-
npx kenobi-pages schema push "My Page" '{"fields":{"headline":{"type":"string"}}}'
|
|
420
|
-
npx kenobi-pages types 42 > lib/kenobi-types.ts
|
|
421
|
-
npx kenobi-pages page get 42 acme-corp
|
|
422
|
-
npx kenobi-pages workflows
|
|
423
|
-
npx kenobi-pages run 42 --params '{"slug":"acme-corp"}'
|
|
424
|
-
|
|
425
|
-
Output:
|
|
426
|
-
All data is written as JSON to stdout. Status messages go to stderr.
|
|
427
|
-
Pipe stdout to jq, a file, or another command safely.
|
|
428
|
-
|
|
429
|
-
Exit codes:
|
|
430
|
-
0 Success
|
|
431
|
-
1 API or network error
|
|
432
|
-
2 Invalid usage (bad arguments)
|
|
433
|
-
3 Resource not found (404)
|
|
434
|
-
4 Unauthorized (invalid API key)
|
|
435
|
-
|
|
436
|
-
Environment:
|
|
437
|
-
KENOBI_PAGES_KEY Org public key. Set via 'init' or manually.
|
|
438
|
-
KENOBI_BASE_URL Optional. Override the Kenobi API base URL.
|
|
439
|
-
|
|
440
|
-
Key resolution order:
|
|
441
|
-
1. KENOBI_PAGES_KEY environment variable
|
|
442
|
-
2. ~/.kenobi/config.json (written by 'init')
|
|
443
|
-
`
|
|
444
|
-
|
|
445
|
-
const [, , ...argv] = process.argv
|
|
446
|
-
|
|
447
|
-
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
448
|
-
console.log(HELP)
|
|
449
|
-
process.exit(0)
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
const [group, action, ...rest] = argv
|
|
453
|
-
|
|
454
|
-
if (group === "init") {
|
|
455
|
-
await initCommand()
|
|
456
|
-
} else if (group === "schema" && action === "get") {
|
|
457
|
-
await schemaGet(rest)
|
|
458
|
-
} else if (group === "schema" && action === "push") {
|
|
459
|
-
await schemaPush(rest)
|
|
460
|
-
} else if (group === "page" && action === "get") {
|
|
461
|
-
await pageGet(rest)
|
|
462
|
-
} else if (group === "types") {
|
|
463
|
-
await typesGen([action, ...rest])
|
|
464
|
-
} else if (group === "workflows") {
|
|
465
|
-
await listWorkflows()
|
|
466
|
-
} else if (group === "run") {
|
|
467
|
-
await runWorkflow([action, ...rest].filter(Boolean))
|
|
468
|
-
} else {
|
|
469
|
-
console.error(`Unknown command: ${argv.join(" ")}`)
|
|
470
|
-
console.error("Run 'kenobi-pages --help' for usage.")
|
|
471
|
-
process.exit(1)
|
|
472
|
-
}
|
package/src/client.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { KenobiPagesError, KenobiNotFoundError, KenobiUnauthorizedError } from "./errors"
|
|
2
|
-
import type {
|
|
3
|
-
KenobiPagesClient,
|
|
4
|
-
KenobiPagesConfig,
|
|
5
|
-
KenobiFetchOptions,
|
|
6
|
-
KenobiPageResponse,
|
|
7
|
-
KenobiPageSchema,
|
|
8
|
-
KenobiSchemaResponse,
|
|
9
|
-
PostSchemaResponse,
|
|
10
|
-
RunHandle,
|
|
11
|
-
RunStatusResponse,
|
|
12
|
-
WorkflowDetail,
|
|
13
|
-
WorkflowSummary,
|
|
14
|
-
} from "./types"
|
|
15
|
-
|
|
16
|
-
const DEFAULT_BASE_URL = "https://kenobi.ai"
|
|
17
|
-
|
|
18
|
-
// ── Internal fetch helper ──
|
|
19
|
-
|
|
20
|
-
const fetchFromKenobi = async (
|
|
21
|
-
config: KenobiPagesConfig,
|
|
22
|
-
path: string,
|
|
23
|
-
opts?: KenobiFetchOptions & { method?: string; body?: unknown }
|
|
24
|
-
): Promise<Response> => {
|
|
25
|
-
const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "")
|
|
26
|
-
const url = `${baseUrl}${path}`
|
|
27
|
-
|
|
28
|
-
const headers: Record<string, string> = {
|
|
29
|
-
"x-kenobi-key": config.apiKey,
|
|
30
|
-
"Content-Type": "application/json",
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const fetchInit: RequestInit & { next?: { revalidate?: number | false; tags?: readonly string[] } } = {
|
|
34
|
-
method: opts?.method ?? "GET",
|
|
35
|
-
headers,
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (opts?.body !== undefined) {
|
|
39
|
-
fetchInit.body = JSON.stringify(opts.body)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (opts?.revalidate !== undefined || opts?.tags) {
|
|
43
|
-
fetchInit.next = {}
|
|
44
|
-
if (opts.revalidate !== undefined) fetchInit.next.revalidate = opts.revalidate
|
|
45
|
-
if (opts.tags) fetchInit.next.tags = opts.tags
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const response = await fetch(url, fetchInit)
|
|
49
|
-
|
|
50
|
-
if (response.ok) return response
|
|
51
|
-
|
|
52
|
-
if (response.status === 401) {
|
|
53
|
-
throw new KenobiUnauthorizedError()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (response.status === 404) {
|
|
57
|
-
throw new KenobiNotFoundError()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const errorBody = await response.text().catch(() => "Unknown error")
|
|
61
|
-
throw new KenobiPagesError(
|
|
62
|
-
`Kenobi API error (${response.status}): ${errorBody}`,
|
|
63
|
-
response.status,
|
|
64
|
-
"API_ERROR"
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ── Client factory ──
|
|
69
|
-
|
|
70
|
-
export const createKenobiPagesClient = (config: KenobiPagesConfig): KenobiPagesClient => ({
|
|
71
|
-
getPage: async (
|
|
72
|
-
workflowId: number,
|
|
73
|
-
slug: string,
|
|
74
|
-
opts?: KenobiFetchOptions
|
|
75
|
-
): Promise<KenobiPageResponse | null> => {
|
|
76
|
-
try {
|
|
77
|
-
const response = await fetchFromKenobi(config, `/api/v1/pages/${workflowId}/${slug}`, opts)
|
|
78
|
-
return (await response.json()) as KenobiPageResponse
|
|
79
|
-
} catch (err) {
|
|
80
|
-
if (err instanceof KenobiNotFoundError) return null
|
|
81
|
-
throw err
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
getSchema: async (
|
|
86
|
-
workflowId: number,
|
|
87
|
-
opts?: KenobiFetchOptions
|
|
88
|
-
): Promise<KenobiSchemaResponse> => {
|
|
89
|
-
const response = await fetchFromKenobi(config, `/api/v1/pages/${workflowId}/schema`, opts)
|
|
90
|
-
return (await response.json()) as KenobiSchemaResponse
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
postSchema: async (name: string, schema: KenobiPageSchema): Promise<PostSchemaResponse> => {
|
|
94
|
-
const response = await fetchFromKenobi(config, "/api/v1/pages/schema", {
|
|
95
|
-
method: "POST",
|
|
96
|
-
body: { name, schema },
|
|
97
|
-
})
|
|
98
|
-
return (await response.json()) as PostSchemaResponse
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
listWorkflows: async (): Promise<readonly WorkflowSummary[]> => {
|
|
102
|
-
const response = await fetchFromKenobi(config, "/api/v1/workflows")
|
|
103
|
-
const data = (await response.json()) as { workflows: WorkflowSummary[] }
|
|
104
|
-
return data.workflows
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
getWorkflow: async (workflowId: number): Promise<WorkflowDetail> => {
|
|
108
|
-
const response = await fetchFromKenobi(config, `/api/v1/workflows/${workflowId}`)
|
|
109
|
-
return (await response.json()) as WorkflowDetail
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
triggerRun: async (workflowId: number, params: Record<string, string>): Promise<RunHandle> => {
|
|
113
|
-
const response = await fetchFromKenobi(config, `/api/v1/workflows/${workflowId}/run`, {
|
|
114
|
-
method: "POST",
|
|
115
|
-
body: { params },
|
|
116
|
-
})
|
|
117
|
-
return (await response.json()) as RunHandle
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
getRunStatus: async (workflowId: number, runId: string): Promise<RunStatusResponse> => {
|
|
121
|
-
const response = await fetchFromKenobi(
|
|
122
|
-
config,
|
|
123
|
-
`/api/v1/workflows/${workflowId}/runs/${runId}`
|
|
124
|
-
)
|
|
125
|
-
return (await response.json()) as RunStatusResponse
|
|
126
|
-
},
|
|
127
|
-
})
|
package/src/errors.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export class KenobiPagesError extends Error {
|
|
2
|
-
readonly status: number
|
|
3
|
-
readonly code: string
|
|
4
|
-
|
|
5
|
-
constructor(message: string, status: number, code: string) {
|
|
6
|
-
super(message)
|
|
7
|
-
this.name = "KenobiPagesError"
|
|
8
|
-
this.status = status
|
|
9
|
-
this.code = code
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class KenobiNotFoundError extends KenobiPagesError {
|
|
14
|
-
constructor(message = "Resource not found") {
|
|
15
|
-
super(message, 404, "NOT_FOUND")
|
|
16
|
-
this.name = "KenobiNotFoundError"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class KenobiUnauthorizedError extends KenobiPagesError {
|
|
21
|
-
constructor(message = "Unauthorized — check your API key") {
|
|
22
|
-
super(message, 401, "UNAUTHORIZED")
|
|
23
|
-
this.name = "KenobiUnauthorizedError"
|
|
24
|
-
}
|
|
25
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export { createKenobiPagesClient } from "./client"
|
|
2
|
-
export { KenobiPagesError, KenobiNotFoundError, KenobiUnauthorizedError } from "./errors"
|
|
3
|
-
export type {
|
|
4
|
-
KenobiPagesClient,
|
|
5
|
-
KenobiPagesConfig,
|
|
6
|
-
KenobiFetchOptions,
|
|
7
|
-
KenobiPageResponse,
|
|
8
|
-
KenobiPageSchema,
|
|
9
|
-
KenobiSchemaResponse,
|
|
10
|
-
OutputFieldSpec,
|
|
11
|
-
PostSchemaResponse,
|
|
12
|
-
RunHandle,
|
|
13
|
-
RunStatus,
|
|
14
|
-
RunStatusResponse,
|
|
15
|
-
WorkflowDetail,
|
|
16
|
-
WorkflowParam,
|
|
17
|
-
WorkflowSummary,
|
|
18
|
-
} from "./types"
|
package/src/types.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// ── Client configuration ──
|
|
2
|
-
|
|
3
|
-
export interface KenobiPagesConfig {
|
|
4
|
-
/** Org-scoped public key from the Kenobi workflow builder (pk_live_... or pk_test_...). */
|
|
5
|
-
readonly apiKey: string
|
|
6
|
-
/** Base URL of the Kenobi API. Defaults to https://kenobi.ai */
|
|
7
|
-
readonly baseUrl?: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// ── Next.js fetch options ──
|
|
11
|
-
|
|
12
|
-
export interface KenobiFetchOptions {
|
|
13
|
-
/** Next.js ISR revalidation interval in seconds, or `false` to disable caching. */
|
|
14
|
-
readonly revalidate?: number | false
|
|
15
|
-
/** Next.js cache tags for on-demand revalidation via `revalidateTag()`. */
|
|
16
|
-
readonly tags?: readonly string[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// ── API response types ──
|
|
20
|
-
|
|
21
|
-
export interface KenobiPageResponse {
|
|
22
|
-
readonly content: Record<string, unknown>
|
|
23
|
-
readonly metadata: Record<string, unknown> | null
|
|
24
|
-
readonly updatedAt: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface KenobiSchemaResponse {
|
|
28
|
-
readonly schema: Record<string, unknown>
|
|
29
|
-
readonly provider: string
|
|
30
|
-
readonly title: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface PostSchemaResponse {
|
|
34
|
-
readonly sourceKey: string
|
|
35
|
-
readonly name: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ── Schema DSL types (standalone — no @kenobi/cortex dependency) ──
|
|
39
|
-
|
|
40
|
-
interface FieldSpecBase {
|
|
41
|
-
readonly description?: string
|
|
42
|
-
readonly optional?: boolean
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type OutputFieldSpec =
|
|
46
|
-
| ({ readonly type: "string"; readonly min?: number; readonly max?: number } & FieldSpecBase)
|
|
47
|
-
| ({ readonly type: "url" } & FieldSpecBase)
|
|
48
|
-
| ({
|
|
49
|
-
readonly type: "number"
|
|
50
|
-
readonly min?: number
|
|
51
|
-
readonly max?: number
|
|
52
|
-
readonly integer?: boolean
|
|
53
|
-
} & FieldSpecBase)
|
|
54
|
-
| ({ readonly type: "boolean" } & FieldSpecBase)
|
|
55
|
-
| ({ readonly type: "enum"; readonly values?: readonly string[] } & FieldSpecBase)
|
|
56
|
-
| ({
|
|
57
|
-
readonly type: "object"
|
|
58
|
-
readonly fields: Readonly<Record<string, OutputFieldSpec>>
|
|
59
|
-
} & FieldSpecBase)
|
|
60
|
-
| ({
|
|
61
|
-
readonly type: "array"
|
|
62
|
-
readonly items: OutputFieldSpec
|
|
63
|
-
readonly min?: number
|
|
64
|
-
readonly max?: number
|
|
65
|
-
} & FieldSpecBase)
|
|
66
|
-
|
|
67
|
-
export interface KenobiPageSchema {
|
|
68
|
-
readonly fields: Readonly<Record<string, OutputFieldSpec>>
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ── Workflow types ──
|
|
72
|
-
|
|
73
|
-
export interface WorkflowParam {
|
|
74
|
-
readonly name: string
|
|
75
|
-
readonly description?: string
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface WorkflowSummary {
|
|
79
|
-
readonly id: number
|
|
80
|
-
readonly name: string
|
|
81
|
-
readonly slug: string
|
|
82
|
-
readonly params: readonly WorkflowParam[]
|
|
83
|
-
readonly outputProvider: string | null
|
|
84
|
-
readonly outputTitle: string | null
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface WorkflowDetail {
|
|
88
|
-
readonly id: number
|
|
89
|
-
readonly name: string
|
|
90
|
-
readonly slug: string
|
|
91
|
-
readonly params: readonly WorkflowParam[]
|
|
92
|
-
readonly output: {
|
|
93
|
-
readonly provider: string | null
|
|
94
|
-
readonly title: string | null
|
|
95
|
-
readonly schema: Record<string, unknown> | null
|
|
96
|
-
}
|
|
97
|
-
readonly destinations: readonly { readonly adapter: string }[]
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface RunHandle {
|
|
101
|
-
readonly runId: string
|
|
102
|
-
readonly status: string
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export type RunStatus = "QUEUED" | "EXECUTING" | "COMPLETED" | "FAILED" | "CANCELED"
|
|
106
|
-
|
|
107
|
-
export interface RunStatusResponse {
|
|
108
|
-
readonly runId: string
|
|
109
|
-
readonly status: RunStatus
|
|
110
|
-
readonly output: Record<string, unknown> | null
|
|
111
|
-
readonly createdAt: string
|
|
112
|
-
readonly finishedAt: string | null
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// ── Client interface ──
|
|
116
|
-
|
|
117
|
-
export interface KenobiPagesClient {
|
|
118
|
-
readonly getPage: (
|
|
119
|
-
workflowId: number,
|
|
120
|
-
slug: string,
|
|
121
|
-
opts?: KenobiFetchOptions
|
|
122
|
-
) => Promise<KenobiPageResponse | null>
|
|
123
|
-
readonly getSchema: (
|
|
124
|
-
workflowId: number,
|
|
125
|
-
opts?: KenobiFetchOptions
|
|
126
|
-
) => Promise<KenobiSchemaResponse>
|
|
127
|
-
readonly postSchema: (name: string, schema: KenobiPageSchema) => Promise<PostSchemaResponse>
|
|
128
|
-
readonly listWorkflows: () => Promise<readonly WorkflowSummary[]>
|
|
129
|
-
readonly getWorkflow: (workflowId: number) => Promise<WorkflowDetail>
|
|
130
|
-
readonly triggerRun: (workflowId: number, params: Record<string, string>) => Promise<RunHandle>
|
|
131
|
-
readonly getRunStatus: (workflowId: number, runId: string) => Promise<RunStatusResponse>
|
|
132
|
-
}
|