terse-cli 0.1.0
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/api.d.ts +3 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +50 -0
- package/dist/api.js.map +1 -0
- package/dist/assertProjectRoot.d.ts +6 -0
- package/dist/assertProjectRoot.d.ts.map +1 -0
- package/dist/assertProjectRoot.js +19 -0
- package/dist/assertProjectRoot.js.map +1 -0
- package/dist/codegen.d.ts +120 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +786 -0
- package/dist/codegen.js.map +1 -0
- package/dist/deploy.d.ts +2 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +124 -0
- package/dist/deploy.js.map +1 -0
- package/dist/generate.d.ts +2 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +284 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +150 -0
- package/dist/init.js.map +1 -0
- package/dist/integrate.d.ts +2 -0
- package/dist/integrate.d.ts.map +1 -0
- package/dist/integrate.js +34 -0
- package/dist/integrate.js.map +1 -0
- package/dist/loadJob.d.ts +10 -0
- package/dist/loadJob.d.ts.map +1 -0
- package/dist/loadJob.js +86 -0
- package/dist/loadJob.js.map +1 -0
- package/dist/run.d.ts +12 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +164 -0
- package/dist/run.js.map +1 -0
- package/dist/shared/ApiRoutes.d.ts +274 -0
- package/dist/shared/ApiRoutes.d.ts.map +1 -0
- package/dist/shared/ApiRoutes.js +269 -0
- package/dist/shared/ApiRoutes.js.map +1 -0
- package/dist/shared/ClientBoundTools.d.ts +37 -0
- package/dist/shared/ClientBoundTools.d.ts.map +1 -0
- package/dist/shared/ClientBoundTools.js +37 -0
- package/dist/shared/ClientBoundTools.js.map +1 -0
- package/dist/shared/Configs.d.ts +425 -0
- package/dist/shared/Configs.d.ts.map +1 -0
- package/dist/shared/Configs.js +703 -0
- package/dist/shared/Configs.js.map +1 -0
- package/dist/shared/DonatedState.d.ts +5 -0
- package/dist/shared/DonatedState.d.ts.map +1 -0
- package/dist/shared/DonatedState.js +13 -0
- package/dist/shared/DonatedState.js.map +1 -0
- package/dist/shared/Entities.d.ts +8 -0
- package/dist/shared/Entities.d.ts.map +1 -0
- package/dist/shared/Entities.js +9 -0
- package/dist/shared/Entities.js.map +1 -0
- package/dist/shared/FrontendRoutes.d.ts +52 -0
- package/dist/shared/FrontendRoutes.d.ts.map +1 -0
- package/dist/shared/FrontendRoutes.js +52 -0
- package/dist/shared/FrontendRoutes.js.map +1 -0
- package/dist/shared/Integrations.d.ts +218 -0
- package/dist/shared/Integrations.d.ts.map +1 -0
- package/dist/shared/Integrations.js +134 -0
- package/dist/shared/Integrations.js.map +1 -0
- package/dist/shared/InvalidationKeys.d.ts +45 -0
- package/dist/shared/InvalidationKeys.d.ts.map +1 -0
- package/dist/shared/InvalidationKeys.js +150 -0
- package/dist/shared/InvalidationKeys.js.map +1 -0
- package/dist/shared/ModelEvents.d.ts +166 -0
- package/dist/shared/ModelEvents.d.ts.map +1 -0
- package/dist/shared/ModelEvents.js +14 -0
- package/dist/shared/ModelEvents.js.map +1 -0
- package/dist/shared/Notifications.d.ts +32 -0
- package/dist/shared/Notifications.d.ts.map +1 -0
- package/dist/shared/Notifications.js +6 -0
- package/dist/shared/Notifications.js.map +1 -0
- package/dist/shared/RunHistoryTypes.d.ts +94 -0
- package/dist/shared/RunHistoryTypes.d.ts.map +1 -0
- package/dist/shared/RunHistoryTypes.js +10 -0
- package/dist/shared/RunHistoryTypes.js.map +1 -0
- package/dist/shared/SocketEvents.d.ts +49 -0
- package/dist/shared/SocketEvents.d.ts.map +1 -0
- package/dist/shared/SocketEvents.js +53 -0
- package/dist/shared/SocketEvents.js.map +1 -0
- package/dist/shared/Survey.d.ts +10 -0
- package/dist/shared/Survey.d.ts.map +1 -0
- package/dist/shared/Survey.js +2 -0
- package/dist/shared/Survey.js.map +1 -0
- package/dist/shared/TicketSystem.d.ts +154 -0
- package/dist/shared/TicketSystem.d.ts.map +1 -0
- package/dist/shared/TicketSystem.js +21 -0
- package/dist/shared/TicketSystem.js.map +1 -0
- package/dist/shared/ToolsTypes.d.ts +18 -0
- package/dist/shared/ToolsTypes.d.ts.map +1 -0
- package/dist/shared/ToolsTypes.js +2 -0
- package/dist/shared/ToolsTypes.js.map +1 -0
- package/dist/shared/types.d.ts +744 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +16 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +62 -0
- package/dist/test.js.map +1 -0
- package/dist/util.d.ts +12 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +20 -0
- package/dist/util.js.map +1 -0
- package/package.json +35 -0
- package/templates/env.example.tmpl +1 -0
- package/templates/gitignore.tmpl +3 -0
- package/templates/package.json.tmpl +15 -0
- package/templates/src/index.ts.tmpl +28 -0
- package/templates/tsconfig.json.tmpl +19 -0
package/dist/init.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { exec, execSync } from "node:child_process";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import ora from "ora";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { input } from "@inquirer/prompts";
|
|
9
|
+
import { generate } from "./generate.js";
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
const FRONTEND_URL = process.env.TERSE_FRONTEND_URL || "http://localhost:5173";
|
|
14
|
+
const BACKEND_URL = process.env.TERSE_BACKEND_URL || "http://localhost:3001";
|
|
15
|
+
export async function init(projectName) {
|
|
16
|
+
const targetDir = projectName ? path.resolve(process.cwd(), projectName) : process.cwd();
|
|
17
|
+
const resolvedName = projectName ?? path.basename(process.cwd());
|
|
18
|
+
console.log(`\n Creating Terse project ${chalk.bold(resolvedName)}\n`);
|
|
19
|
+
// Create target directory if it doesn't exist
|
|
20
|
+
if (projectName) {
|
|
21
|
+
if (fs.existsSync(targetDir)) {
|
|
22
|
+
console.error(chalk.red(`Error: Directory "${projectName}" already exists.`));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
// Create src directory
|
|
28
|
+
fs.mkdirSync(path.join(targetDir, "src"), { recursive: true });
|
|
29
|
+
const templatesDir = getTemplatesDir();
|
|
30
|
+
const replacements = { PROJECT_NAME: resolvedName };
|
|
31
|
+
// Write files from templates
|
|
32
|
+
const files = [
|
|
33
|
+
{ template: "package.json.tmpl", output: "package.json" },
|
|
34
|
+
{ template: "tsconfig.json.tmpl", output: "tsconfig.json" },
|
|
35
|
+
{ template: "src/index.ts.tmpl", output: "src/index.ts" },
|
|
36
|
+
{ template: "env.example.tmpl", output: ".env.example" },
|
|
37
|
+
{ template: "gitignore.tmpl", output: ".gitignore" },
|
|
38
|
+
];
|
|
39
|
+
for (const file of files) {
|
|
40
|
+
const content = readTemplate(templatesDir, file.template);
|
|
41
|
+
const rendered = applyReplacements(content, replacements);
|
|
42
|
+
const outputPath = path.join(targetDir, file.output);
|
|
43
|
+
fs.writeFileSync(outputPath, rendered);
|
|
44
|
+
console.log(` ${chalk.green("+")} ${file.output}`);
|
|
45
|
+
}
|
|
46
|
+
// Install dependencies
|
|
47
|
+
const pm = detectPackageManager();
|
|
48
|
+
const spinner = ora(`Installing dependencies with ${pm}`).start();
|
|
49
|
+
try {
|
|
50
|
+
await execAsync(`${pm} install`, { cwd: targetDir });
|
|
51
|
+
spinner.succeed(`Dependencies installed with ${pm}`);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
spinner.warn(`Failed to install dependencies. Run ${chalk.cyan(`${pm} install`)} manually.`);
|
|
55
|
+
}
|
|
56
|
+
// Prompt for API key and write .env
|
|
57
|
+
await promptForApiKey(targetDir);
|
|
58
|
+
const envExists = fs.existsSync(path.join(targetDir, ".env"));
|
|
59
|
+
try {
|
|
60
|
+
await generate();
|
|
61
|
+
spinner.succeed(`Generated code`);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
spinner.warn(`Failed to generate code. Run ${chalk.cyan(`$terse generate`)} manually.`);
|
|
65
|
+
}
|
|
66
|
+
console.log(`\n ${chalk.green.bold("Done!")} Your Terse project is ready.\n`);
|
|
67
|
+
console.log(" Next steps:\n");
|
|
68
|
+
let step = 1;
|
|
69
|
+
if (projectName) {
|
|
70
|
+
console.log(` ${step}. cd ${projectName}`);
|
|
71
|
+
step++;
|
|
72
|
+
}
|
|
73
|
+
if (!envExists) {
|
|
74
|
+
console.log(` ${step}. Copy .env.example to .env and add your TERSE_API_KEY`);
|
|
75
|
+
step++;
|
|
76
|
+
}
|
|
77
|
+
console.log(` ${step}. Edit src/index.ts to define your job`);
|
|
78
|
+
step++;
|
|
79
|
+
console.log(` ${step}. ${pm} run build Build the project`);
|
|
80
|
+
step++;
|
|
81
|
+
console.log(` ${step}. ${pm} run dev Run in development mode\n`);
|
|
82
|
+
}
|
|
83
|
+
async function promptForApiKey(targetDir) {
|
|
84
|
+
console.log(`\n Create an API key at: ${chalk.cyan(`${FRONTEND_URL}/app/profile?tab=api-tokens`)}\n`);
|
|
85
|
+
try {
|
|
86
|
+
const key = (await input({ message: "Paste your API key (or press Enter to skip):" })).trim();
|
|
87
|
+
if (!key) {
|
|
88
|
+
fs.writeFileSync(path.join(targetDir, ".env"), "TERSE_API_KEY=\n");
|
|
89
|
+
console.log(chalk.dim(" Skipped — you can add TERSE_API_KEY to .env later."));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Validate the key against the backend
|
|
93
|
+
const spinner = ora("Verifying API key").start();
|
|
94
|
+
try {
|
|
95
|
+
const res = await fetch(`${BACKEND_URL}/sdk/me`, {
|
|
96
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
97
|
+
});
|
|
98
|
+
if (res.ok) {
|
|
99
|
+
const data = await res.json();
|
|
100
|
+
const name = data.firstName || data.displayName || data.email || "there";
|
|
101
|
+
spinner.succeed(`Hello, ${name}! API key verified.`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
spinner.warn("Could not verify API key (invalid or server error). Saving it anyway.");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
spinner.warn("Could not reach the server to verify your API key. Saving it anyway.");
|
|
109
|
+
}
|
|
110
|
+
fs.writeFileSync(path.join(targetDir, ".env"), `TERSE_API_KEY=${key}\n`);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (error instanceof Error && error.name === "ExitPromptError") {
|
|
114
|
+
console.log("\n");
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function getTemplatesDir() {
|
|
121
|
+
// In dist/, templates are at ../templates relative to the compiled file
|
|
122
|
+
const fromDist = path.resolve(__dirname, "..", "templates");
|
|
123
|
+
if (fs.existsSync(fromDist))
|
|
124
|
+
return fromDist;
|
|
125
|
+
// Fallback for development
|
|
126
|
+
const fromSrc = path.resolve(__dirname, "..", "..", "templates");
|
|
127
|
+
if (fs.existsSync(fromSrc))
|
|
128
|
+
return fromSrc;
|
|
129
|
+
throw new Error("Could not find templates directory");
|
|
130
|
+
}
|
|
131
|
+
function readTemplate(templatesDir, templatePath) {
|
|
132
|
+
return fs.readFileSync(path.join(templatesDir, templatePath), "utf-8");
|
|
133
|
+
}
|
|
134
|
+
function applyReplacements(content, replacements) {
|
|
135
|
+
let result = content;
|
|
136
|
+
for (const [token, value] of Object.entries(replacements)) {
|
|
137
|
+
result = result.replaceAll(`{{${token}}}`, value);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
function detectPackageManager() {
|
|
142
|
+
try {
|
|
143
|
+
execSync("pnpm --version", { stdio: "ignore" });
|
|
144
|
+
return "pnpm";
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return "npm";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;AAEjC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,uBAAuB,CAAA;AAC9E,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,uBAAuB,CAAA;AAE5E,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,WAAoB;IAC3C,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;IACxF,MAAM,YAAY,GAAG,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAEhE,OAAO,CAAC,GAAG,CAAC,8BAA8B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IAEvE,8CAA8C;IAC9C,IAAI,WAAW,EAAE,CAAC;QACd,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,WAAW,mBAAmB,CAAC,CAAC,CAAA;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,uBAAuB;IACvB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE9D,MAAM,YAAY,GAAG,eAAe,EAAE,CAAA;IACtC,MAAM,YAAY,GAAG,EAAE,YAAY,EAAE,YAAY,EAAE,CAAA;IAEnD,6BAA6B;IAC7B,MAAM,KAAK,GAAgD;QACvD,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,EAAE;QACzD,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE;QAC3D,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,EAAE;QACzD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE;QACxD,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,EAAE;KACvD,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACpD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,uBAAuB;IACvB,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAAA;IACjC,MAAM,OAAO,GAAG,GAAG,CAAC,gCAAgC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;IAEjE,IAAI,CAAC;QACD,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAA;QACpD,OAAO,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAA;IACxD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,IAAI,CAAC,uCAAuC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,YAAY,CAAC,CAAA;IAChG,CAAC;IAED,oCAAoC;IACpC,MAAM,eAAe,CAAC,SAAS,CAAC,CAAA;IAEhC,MAAM,SAAS,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAE7D,IAAI,CAAC;QACD,MAAM,QAAQ,EAAE,CAAA;QAChB,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,IAAI,CAAC,gCAAgC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAA;IAC3F,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAA;IAC9E,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAE9B,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,IAAI,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,QAAQ,WAAW,EAAE,CAAC,CAAA;QAC3C,IAAI,EAAE,CAAA;IACV,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,wDAAwD,CAAC,CAAA;QAC9E,IAAI,EAAE,CAAA;IACV,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,wCAAwC,CAAC,CAAA;IAC9D,IAAI,EAAE,CAAA;IACN,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,EAAE,iCAAiC,CAAC,CAAA;IAC9D,IAAI,EAAE,CAAA;IACN,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,EAAE,yCAAyC,CAAC,CAAA;AAC1E,CAAC;AAGD,KAAK,UAAU,eAAe,CAAC,SAAiB;IAC5C,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,6BAA6B,CAAC,IAAI,CAAC,CAAA;IAEtG,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAE7F,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAA;YAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC,CAAA;YAC9E,OAAM;QACV,CAAC;QAED,uCAAuC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAA;QAEhD,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,SAAS,EAAE;gBAC7C,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,GAAG,EAAE,EAAE;aAC9C,CAAC,CAAA;YAEF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACT,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAuF,CAAA;gBAClH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,CAAA;gBACxE,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,qBAAqB,CAAC,CAAA;YACxD,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAA;YACzF,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAA;QACxF,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC,CAAA;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;QACD,MAAM,KAAK,CAAA;IACf,CAAC;AACL,CAAC;AAED,SAAS,eAAe;IACpB,wEAAwE;IACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;IAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAA;IAE5C,2BAA2B;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;IAChE,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IAE1C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,YAAoB;IAC5D,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;AAC1E,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,YAAoC;IAC5E,IAAI,MAAM,GAAG,OAAO,CAAA;IACpB,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACxD,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,KAAK,IAAI,EAAE,KAAK,CAAC,CAAA;IACrD,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,SAAS,oBAAoB;IACzB,IAAI,CAAC;QACD,QAAQ,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC/C,OAAO,MAAM,CAAA;IACjB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrate.d.ts","sourceRoot":"","sources":["../src/integrate.ts"],"names":[],"mappings":"AAMA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAa/C"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
const FRONTEND_URL = "http://localhost:5173";
|
|
4
|
+
const INTEGRATIONS_URL = `${FRONTEND_URL}/app/integrations`;
|
|
5
|
+
export async function integrate() {
|
|
6
|
+
console.log("");
|
|
7
|
+
console.log(` Open integrations in the Web UI: ${chalk.cyan(INTEGRATIONS_URL)}`);
|
|
8
|
+
console.log("");
|
|
9
|
+
const opened = openInBrowser(INTEGRATIONS_URL);
|
|
10
|
+
if (opened) {
|
|
11
|
+
console.log(chalk.green(" Opened in your default browser."));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
console.log(chalk.yellow(" Could not open browser automatically."));
|
|
15
|
+
console.log(` Open manually: ${chalk.cyan(INTEGRATIONS_URL)}`);
|
|
16
|
+
}
|
|
17
|
+
function openInBrowser(url) {
|
|
18
|
+
try {
|
|
19
|
+
if (process.platform === "darwin") {
|
|
20
|
+
spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (process.platform === "win32") {
|
|
24
|
+
spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=integrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrate.js","sourceRoot":"","sources":["../src/integrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,YAAY,GAAG,uBAAuB,CAAA;AAC5C,MAAM,gBAAgB,GAAG,GAAG,YAAY,mBAAmB,CAAA;AAE3D,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,sCAAsC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACjF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAEf,MAAM,MAAM,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAA;IAC9C,IAAI,MAAM,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA;QAC7D,OAAM;IACV,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,CAAA;IACpE,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAC9B,IAAI,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;YACjE,OAAO,IAAI,CAAA;QACf,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC/B,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;YACnF,OAAO,IAAI,CAAA;QACf,CAAC;QACD,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;QACrE,OAAO,IAAI,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CreateJobParameters } from "terse-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Imports the user's entry file and returns the full job registry.
|
|
4
|
+
* Each createJob() call in src/index.ts populates this map.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadJobRegistry(): Promise<Map<string, CreateJobParameters>>;
|
|
7
|
+
export declare function loadJob(jobName?: string): Promise<{
|
|
8
|
+
job: CreateJobParameters;
|
|
9
|
+
}>;
|
|
10
|
+
//# sourceMappingURL=loadJob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadJob.d.ts","sourceRoot":"","sources":["../src/loadJob.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAG/C;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CA4CjF;AAED,wBAAsB,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,mBAAmB,CAAA;CAAE,CAAC,CA0BrF"}
|
package/dist/loadJob.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { select } from "@inquirer/prompts";
|
|
5
|
+
import { tsImport } from "tsx/esm/api";
|
|
6
|
+
import { assertProjectRoot } from "./assertProjectRoot.js";
|
|
7
|
+
/**
|
|
8
|
+
* Imports the user's entry file and returns the full job registry.
|
|
9
|
+
* Each createJob() call in src/index.ts populates this map.
|
|
10
|
+
*/
|
|
11
|
+
export async function loadJobRegistry() {
|
|
12
|
+
assertProjectRoot();
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const entryPath = path.join(cwd, "src", "index.ts");
|
|
15
|
+
// Import the user's entry file via tsx — this triggers createJob() calls which
|
|
16
|
+
// populate the global job registry on globalThis.__terse_jobRegistry.
|
|
17
|
+
const parentURL = pathToFileURL(path.join(cwd, "package.json")).href;
|
|
18
|
+
try {
|
|
19
|
+
await tsImport(entryPath, parentURL);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (isModuleNotFoundError(err)) {
|
|
23
|
+
const pkg = extractMissingPackage(err);
|
|
24
|
+
console.error(chalk.red(`Error: Cannot find package '${pkg}' imported from src/index.ts`));
|
|
25
|
+
if (pkg === "terse-sdk") {
|
|
26
|
+
console.error(chalk.dim("\nMake sure terse-sdk is linked or installed in your project:"));
|
|
27
|
+
console.error(chalk.dim(" pnpm link terse-sdk"));
|
|
28
|
+
console.error(chalk.dim(" # or"));
|
|
29
|
+
console.error(chalk.dim(" npm install terse-sdk"));
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error(chalk.dim(`\nInstall the missing package: pnpm add ${pkg}`));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.error(chalk.red("Error importing src/index.ts:\n"));
|
|
37
|
+
console.error(err);
|
|
38
|
+
}
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
// Read the registry from globalThis — populated by createJob() during the import above.
|
|
42
|
+
// We use globalThis rather than importing the SDK again because tsx may load separate
|
|
43
|
+
// module instances, which would give us an empty registry.
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
const registry = globalThis.__terse_jobRegistry;
|
|
46
|
+
if (!registry || registry.size === 0) {
|
|
47
|
+
console.error(chalk.red("No jobs found. Make sure your src/index.ts calls client.createJob()."));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
return registry;
|
|
51
|
+
}
|
|
52
|
+
export async function loadJob(jobName) {
|
|
53
|
+
const registry = await loadJobRegistry();
|
|
54
|
+
// Resolve which job to run
|
|
55
|
+
let resolvedName;
|
|
56
|
+
if (jobName) {
|
|
57
|
+
if (!registry.has(jobName)) {
|
|
58
|
+
console.error(chalk.red(`Job "${jobName}" not found.`));
|
|
59
|
+
console.log("\nAvailable jobs:");
|
|
60
|
+
for (const name of registry.keys()) {
|
|
61
|
+
console.log(` - ${name}`);
|
|
62
|
+
}
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
resolvedName = jobName;
|
|
66
|
+
}
|
|
67
|
+
else if (registry.size === 1) {
|
|
68
|
+
resolvedName = registry.keys().next().value;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
resolvedName = await select({
|
|
72
|
+
message: "Multiple jobs found. Which one?",
|
|
73
|
+
choices: [...registry.keys()].map(name => ({ name, value: name })),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return { job: registry.get(resolvedName) };
|
|
77
|
+
}
|
|
78
|
+
function isModuleNotFoundError(err) {
|
|
79
|
+
return err instanceof Error && err.code === "ERR_MODULE_NOT_FOUND";
|
|
80
|
+
}
|
|
81
|
+
function extractMissingPackage(err) {
|
|
82
|
+
// Node's error message format: "Cannot find package 'foo' imported from ..."
|
|
83
|
+
const match = err.message.match(/Cannot find package '([^']+)'/);
|
|
84
|
+
return match?.[1] ?? "unknown";
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=loadJob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadJob.js","sourceRoot":"","sources":["../src/loadJob.ts"],"names":[],"mappings":"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"}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CreateJobParameters } from "terse-sdk";
|
|
2
|
+
import type { SerializedEvent } from "./shared/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a TerseAgent scoped to a job's skills and execute onTrigger.
|
|
5
|
+
* Tools are registered from the codegen factory on globalThis (needed because
|
|
6
|
+
* tsx may load a separate module instance of terse-sdk).
|
|
7
|
+
*/
|
|
8
|
+
export declare function executeJob(job: CreateJobParameters, event: SerializedEvent, options?: {
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function run(jobName?: string, eventJson?: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAc,MAAM,WAAW,CAAA;AAK3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAKxD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,mBAAmB,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCjI;AAED,wBAAsB,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB7E"}
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { TerseAgent } from "terse-sdk";
|
|
3
|
+
import { readApiKey } from "./api.js";
|
|
4
|
+
import { assertProjectRoot } from "./assertProjectRoot.js";
|
|
5
|
+
import { loadJob } from "./loadJob.js";
|
|
6
|
+
import { ApiRoutes } from "./shared/ApiRoutes.js";
|
|
7
|
+
import { convertSerializedEventToInputEvent } from "./util.js";
|
|
8
|
+
const BACKEND_URL = process.env.TERSE_BACKEND_URL || "http://localhost:3001";
|
|
9
|
+
/**
|
|
10
|
+
* Create a TerseAgent scoped to a job's skills and execute onTrigger.
|
|
11
|
+
* Tools are registered from the codegen factory on globalThis (needed because
|
|
12
|
+
* tsx may load a separate module instance of terse-sdk).
|
|
13
|
+
*/
|
|
14
|
+
export async function executeJob(job, event, options) {
|
|
15
|
+
const inputEvent = convertSerializedEventToInputEvent(event);
|
|
16
|
+
const isVerbose = options?.verbose ?? false;
|
|
17
|
+
const apiKey = process.env.TERSE_API_KEY ?? null;
|
|
18
|
+
let sessionId;
|
|
19
|
+
let closeSession;
|
|
20
|
+
if (isVerbose && apiKey) {
|
|
21
|
+
const session = await openSessionStream(apiKey);
|
|
22
|
+
sessionId = session.sessionId;
|
|
23
|
+
closeSession = session.close;
|
|
24
|
+
}
|
|
25
|
+
const agent = new TerseAgent(job.skills, BACKEND_URL, sessionId);
|
|
26
|
+
const createTools = globalThis.__terse_createTools;
|
|
27
|
+
if (createTools) {
|
|
28
|
+
Object.defineProperty(agent, "tools", { value: createTools(agent) });
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
if (isVerbose) {
|
|
32
|
+
console.log(chalk.cyan(` Job "${job.name}" started`));
|
|
33
|
+
}
|
|
34
|
+
await job.onTrigger(inputEvent, agent);
|
|
35
|
+
console.log(chalk.green(`\n Job "${job.name}" completed successfully.\n`));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error(chalk.red(`\n Job "${job.name}" threw an error:\n`));
|
|
39
|
+
console.error(err);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
closeSession?.();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function run(jobName, eventJson) {
|
|
47
|
+
assertProjectRoot();
|
|
48
|
+
if (!eventJson) {
|
|
49
|
+
console.error(chalk.red("Error: --event <json> is required.\n"));
|
|
50
|
+
console.error(chalk.dim(" Usage: terse run --event '{\"integrationType\":\"...\",\"formattedContent\":\"...\",\"debugLog\":\"...\"}'"));
|
|
51
|
+
console.error(chalk.dim(" Tip: Use `terse test` to interactively pick a sample event.\n"));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
readApiKey();
|
|
55
|
+
const { job } = await loadJob(jobName);
|
|
56
|
+
console.log(chalk.cyan(`\n Running job: ${job.name}\n`));
|
|
57
|
+
let parsed;
|
|
58
|
+
try {
|
|
59
|
+
parsed = JSON.parse(eventJson);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
console.error(chalk.red("Error: --event value is not valid JSON."));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
await executeJob(job, parsed);
|
|
66
|
+
}
|
|
67
|
+
async function openSessionStream(apiKey) {
|
|
68
|
+
const res = await fetch(`${BACKEND_URL}${ApiRoutes.SDK.SESSION_EVENTS}`, {
|
|
69
|
+
headers: { Authorization: `Bearer ${apiKey}`, Accept: "text/event-stream" }
|
|
70
|
+
});
|
|
71
|
+
if (!res.ok || !res.body) {
|
|
72
|
+
throw new Error(`Failed to open session event stream (HTTP ${res.status})`);
|
|
73
|
+
}
|
|
74
|
+
const reader = res.body.getReader();
|
|
75
|
+
const decoder = new TextDecoder();
|
|
76
|
+
let buffer = "";
|
|
77
|
+
const sessionId = await readSessionId(reader, decoder, buffer);
|
|
78
|
+
buffer = sessionId._remainingBuffer;
|
|
79
|
+
startEventConsumer(reader, decoder, buffer);
|
|
80
|
+
return {
|
|
81
|
+
sessionId: sessionId.value,
|
|
82
|
+
close: () => reader.cancel().catch(() => { })
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function readSessionId(reader, decoder, buffer) {
|
|
86
|
+
while (true) {
|
|
87
|
+
const { done, value } = await reader.read();
|
|
88
|
+
if (done)
|
|
89
|
+
throw new Error("Session stream ended before sending sessionId");
|
|
90
|
+
buffer += decoder.decode(value, { stream: true });
|
|
91
|
+
const lines = buffer.split("\n");
|
|
92
|
+
buffer = lines.pop() ?? "";
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
if (!line.startsWith("data: "))
|
|
95
|
+
continue;
|
|
96
|
+
const event = safeParseJson(line.slice(6));
|
|
97
|
+
if (event?.type === "session_started" && typeof event.sessionId === "string") {
|
|
98
|
+
return { value: event.sessionId, _remainingBuffer: buffer };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function startEventConsumer(reader, decoder, initialBuffer) {
|
|
104
|
+
let buffer = initialBuffer;
|
|
105
|
+
(async () => {
|
|
106
|
+
try {
|
|
107
|
+
while (true) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done)
|
|
110
|
+
break;
|
|
111
|
+
buffer += decoder.decode(value, { stream: true });
|
|
112
|
+
const lines = buffer.split("\n");
|
|
113
|
+
buffer = lines.pop() ?? "";
|
|
114
|
+
for (const line of lines) {
|
|
115
|
+
if (!line.startsWith("data: "))
|
|
116
|
+
continue;
|
|
117
|
+
const event = safeParseJson(line.slice(6));
|
|
118
|
+
if (event)
|
|
119
|
+
logSessionEvent(event);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Stream cancelled by close() — expected
|
|
125
|
+
}
|
|
126
|
+
})();
|
|
127
|
+
}
|
|
128
|
+
function logSessionEvent(event) {
|
|
129
|
+
switch (event.type) {
|
|
130
|
+
case "tool_call_started":
|
|
131
|
+
console.log(chalk.blue(` [tool:start] ${event.toolCallStarted}`));
|
|
132
|
+
break;
|
|
133
|
+
case "tool_call_completed": {
|
|
134
|
+
const parsed = safeParseJson(event.toolCallCompleted);
|
|
135
|
+
const toolName = parsed?.tool || "unknown_tool";
|
|
136
|
+
const status = parsed?.status || "unknown";
|
|
137
|
+
const symbol = status === "completed" ? chalk.green("ok") : chalk.red("failed");
|
|
138
|
+
console.log(` [tool:done] ${toolName} (${symbol})`);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case "action": {
|
|
142
|
+
const action = event.action;
|
|
143
|
+
const actionName = action?.action || "action";
|
|
144
|
+
const target = action?.target ? ` -> ${action.target}` : "";
|
|
145
|
+
console.log(chalk.magenta(` [action] ${actionName}${target}`));
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case "final_output":
|
|
149
|
+
console.log(chalk.green(`\n [final_output] ${event.finalOutput}\n`));
|
|
150
|
+
break;
|
|
151
|
+
case "error":
|
|
152
|
+
console.log(chalk.red(` [error] ${event.message}`));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function safeParseJson(value) {
|
|
157
|
+
try {
|
|
158
|
+
return JSON.parse(value);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|