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.
Files changed (118) hide show
  1. package/dist/api.d.ts +3 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +50 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/assertProjectRoot.d.ts +6 -0
  6. package/dist/assertProjectRoot.d.ts.map +1 -0
  7. package/dist/assertProjectRoot.js +19 -0
  8. package/dist/assertProjectRoot.js.map +1 -0
  9. package/dist/codegen.d.ts +120 -0
  10. package/dist/codegen.d.ts.map +1 -0
  11. package/dist/codegen.js +786 -0
  12. package/dist/codegen.js.map +1 -0
  13. package/dist/deploy.d.ts +2 -0
  14. package/dist/deploy.d.ts.map +1 -0
  15. package/dist/deploy.js +124 -0
  16. package/dist/deploy.js.map +1 -0
  17. package/dist/generate.d.ts +2 -0
  18. package/dist/generate.d.ts.map +1 -0
  19. package/dist/generate.js +284 -0
  20. package/dist/generate.js.map +1 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +57 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/init.d.ts +2 -0
  26. package/dist/init.d.ts.map +1 -0
  27. package/dist/init.js +150 -0
  28. package/dist/init.js.map +1 -0
  29. package/dist/integrate.d.ts +2 -0
  30. package/dist/integrate.d.ts.map +1 -0
  31. package/dist/integrate.js +34 -0
  32. package/dist/integrate.js.map +1 -0
  33. package/dist/loadJob.d.ts +10 -0
  34. package/dist/loadJob.d.ts.map +1 -0
  35. package/dist/loadJob.js +86 -0
  36. package/dist/loadJob.js.map +1 -0
  37. package/dist/run.d.ts +12 -0
  38. package/dist/run.d.ts.map +1 -0
  39. package/dist/run.js +164 -0
  40. package/dist/run.js.map +1 -0
  41. package/dist/shared/ApiRoutes.d.ts +274 -0
  42. package/dist/shared/ApiRoutes.d.ts.map +1 -0
  43. package/dist/shared/ApiRoutes.js +269 -0
  44. package/dist/shared/ApiRoutes.js.map +1 -0
  45. package/dist/shared/ClientBoundTools.d.ts +37 -0
  46. package/dist/shared/ClientBoundTools.d.ts.map +1 -0
  47. package/dist/shared/ClientBoundTools.js +37 -0
  48. package/dist/shared/ClientBoundTools.js.map +1 -0
  49. package/dist/shared/Configs.d.ts +425 -0
  50. package/dist/shared/Configs.d.ts.map +1 -0
  51. package/dist/shared/Configs.js +703 -0
  52. package/dist/shared/Configs.js.map +1 -0
  53. package/dist/shared/DonatedState.d.ts +5 -0
  54. package/dist/shared/DonatedState.d.ts.map +1 -0
  55. package/dist/shared/DonatedState.js +13 -0
  56. package/dist/shared/DonatedState.js.map +1 -0
  57. package/dist/shared/Entities.d.ts +8 -0
  58. package/dist/shared/Entities.d.ts.map +1 -0
  59. package/dist/shared/Entities.js +9 -0
  60. package/dist/shared/Entities.js.map +1 -0
  61. package/dist/shared/FrontendRoutes.d.ts +52 -0
  62. package/dist/shared/FrontendRoutes.d.ts.map +1 -0
  63. package/dist/shared/FrontendRoutes.js +52 -0
  64. package/dist/shared/FrontendRoutes.js.map +1 -0
  65. package/dist/shared/Integrations.d.ts +218 -0
  66. package/dist/shared/Integrations.d.ts.map +1 -0
  67. package/dist/shared/Integrations.js +134 -0
  68. package/dist/shared/Integrations.js.map +1 -0
  69. package/dist/shared/InvalidationKeys.d.ts +45 -0
  70. package/dist/shared/InvalidationKeys.d.ts.map +1 -0
  71. package/dist/shared/InvalidationKeys.js +150 -0
  72. package/dist/shared/InvalidationKeys.js.map +1 -0
  73. package/dist/shared/ModelEvents.d.ts +166 -0
  74. package/dist/shared/ModelEvents.d.ts.map +1 -0
  75. package/dist/shared/ModelEvents.js +14 -0
  76. package/dist/shared/ModelEvents.js.map +1 -0
  77. package/dist/shared/Notifications.d.ts +32 -0
  78. package/dist/shared/Notifications.d.ts.map +1 -0
  79. package/dist/shared/Notifications.js +6 -0
  80. package/dist/shared/Notifications.js.map +1 -0
  81. package/dist/shared/RunHistoryTypes.d.ts +94 -0
  82. package/dist/shared/RunHistoryTypes.d.ts.map +1 -0
  83. package/dist/shared/RunHistoryTypes.js +10 -0
  84. package/dist/shared/RunHistoryTypes.js.map +1 -0
  85. package/dist/shared/SocketEvents.d.ts +49 -0
  86. package/dist/shared/SocketEvents.d.ts.map +1 -0
  87. package/dist/shared/SocketEvents.js +53 -0
  88. package/dist/shared/SocketEvents.js.map +1 -0
  89. package/dist/shared/Survey.d.ts +10 -0
  90. package/dist/shared/Survey.d.ts.map +1 -0
  91. package/dist/shared/Survey.js +2 -0
  92. package/dist/shared/Survey.js.map +1 -0
  93. package/dist/shared/TicketSystem.d.ts +154 -0
  94. package/dist/shared/TicketSystem.d.ts.map +1 -0
  95. package/dist/shared/TicketSystem.js +21 -0
  96. package/dist/shared/TicketSystem.js.map +1 -0
  97. package/dist/shared/ToolsTypes.d.ts +18 -0
  98. package/dist/shared/ToolsTypes.d.ts.map +1 -0
  99. package/dist/shared/ToolsTypes.js +2 -0
  100. package/dist/shared/ToolsTypes.js.map +1 -0
  101. package/dist/shared/types.d.ts +744 -0
  102. package/dist/shared/types.d.ts.map +1 -0
  103. package/dist/shared/types.js +16 -0
  104. package/dist/shared/types.js.map +1 -0
  105. package/dist/test.d.ts +2 -0
  106. package/dist/test.d.ts.map +1 -0
  107. package/dist/test.js +62 -0
  108. package/dist/test.js.map +1 -0
  109. package/dist/util.d.ts +12 -0
  110. package/dist/util.d.ts.map +1 -0
  111. package/dist/util.js +20 -0
  112. package/dist/util.js.map +1 -0
  113. package/package.json +35 -0
  114. package/templates/env.example.tmpl +1 -0
  115. package/templates/gitignore.tmpl +3 -0
  116. package/templates/package.json.tmpl +15 -0
  117. package/templates/src/index.ts.tmpl +28 -0
  118. 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function integrate(): Promise<void>;
2
+ //# sourceMappingURL=integrate.d.ts.map
@@ -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"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}