terse-cli 0.1.25 → 0.1.26
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 +13 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +36 -1
- package/dist/api.js.map +1 -1
- package/dist/commands/attach.d.ts +3 -0
- package/dist/commands/attach.d.ts.map +1 -0
- package/dist/commands/attach.js +65 -0
- package/dist/commands/attach.js.map +1 -0
- package/dist/commands/auth.d.ts +12 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +166 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/deploy.d.ts +3 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +122 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +282 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/history.d.ts +15 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +103 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/historyPrinters.d.ts +9 -0
- package/dist/commands/historyPrinters.d.ts.map +1 -0
- package/dist/commands/historyPrinters.js +101 -0
- package/dist/commands/historyPrinters.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +98 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/integrate.d.ts +3 -0
- package/dist/commands/integrate.d.ts.map +1 -0
- package/dist/commands/integrate.js +214 -0
- package/dist/commands/integrate.js.map +1 -0
- package/dist/commands/replay.d.ts +3 -0
- package/dist/commands/replay.d.ts.map +1 -0
- package/dist/commands/replay.js +20 -0
- package/dist/commands/replay.js.map +1 -0
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +56 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/test.d.ts +3 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +83 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/index.js +42 -12
- package/dist/index.js.map +1 -1
- package/dist/jsonOutput.d.ts +19 -0
- package/dist/jsonOutput.d.ts.map +1 -0
- package/dist/jsonOutput.js +25 -0
- package/dist/jsonOutput.js.map +1 -0
- package/dist/providers/python/PythonProvider.d.ts.map +1 -1
- package/dist/providers/python/PythonProvider.js +10 -1
- package/dist/providers/python/PythonProvider.js.map +1 -1
- package/dist/userConfig.d.ts +5 -0
- package/dist/userConfig.d.ts.map +1 -0
- package/dist/userConfig.js +32 -0
- package/dist/userConfig.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import ora from "ora";
|
|
5
|
+
import { fetchSdkVersion } from "../providers/fetchSdkVersion.js";
|
|
6
|
+
import { resolveProvider } from "../providers/resolveProvider.js";
|
|
7
|
+
import { renderTemplate } from "../providers/templateUtils.js";
|
|
8
|
+
import { loginAndPersist } from "./auth.js";
|
|
9
|
+
import { generate } from "./generate.js";
|
|
10
|
+
import { listAndPromptIntegrations } from "./integrate.js";
|
|
11
|
+
export async function init(projectName, provider = resolveProvider({ command: "init", language: "ts" })) {
|
|
12
|
+
if (!projectName && fs.existsSync(path.join(process.cwd(), "package.json"))) {
|
|
13
|
+
console.error(chalk.red("\n Error: Detected an existing npm project in this directory."));
|
|
14
|
+
console.error(chalk.dim(" terse init is for scaffolding new projects only.\n"));
|
|
15
|
+
console.error(` To add Terse to this project for self-hosted mode, run ${chalk.cyan("terse attach")} instead.\n`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const targetDir = projectName ? path.resolve(process.cwd(), projectName) : process.cwd();
|
|
19
|
+
const resolvedName = projectName ?? path.basename(process.cwd());
|
|
20
|
+
console.log(`\n Creating Terse project ${chalk.bold(resolvedName)}\n`);
|
|
21
|
+
// Create target directory if it doesn't exist
|
|
22
|
+
if (projectName) {
|
|
23
|
+
if (fs.existsSync(targetDir)) {
|
|
24
|
+
console.error(chalk.red(`Error: Directory "${projectName}" already exists.`));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
// Create the source directory up front. Nested template paths create their own parents.
|
|
30
|
+
fs.mkdirSync(path.join(targetDir, "src"), { recursive: true });
|
|
31
|
+
const versionSpinner = ora("Fetching latest SDK version").start();
|
|
32
|
+
const sdkVersion = await fetchSdkVersion(provider.language);
|
|
33
|
+
versionSpinner.succeed(`Using terse-sdk ${sdkVersion}`);
|
|
34
|
+
const templateContext = provider.buildInitTemplateContext(resolvedName, sdkVersion);
|
|
35
|
+
// Write files from templates
|
|
36
|
+
for (const file of provider.scaffoldFiles()) {
|
|
37
|
+
const rendered = renderTemplate(file.template, templateContext);
|
|
38
|
+
const outputPath = path.join(targetDir, file.output);
|
|
39
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
40
|
+
fs.writeFileSync(outputPath, rendered);
|
|
41
|
+
console.log(` ${chalk.green("+")} ${file.output}`);
|
|
42
|
+
}
|
|
43
|
+
// Install dependencies
|
|
44
|
+
const pm = provider.detectPackageManager();
|
|
45
|
+
const spinner = ora(`Installing dependencies with ${pm}`).start();
|
|
46
|
+
// Rest of commands run in newly generated project directory
|
|
47
|
+
await changeDirectory(targetDir);
|
|
48
|
+
try {
|
|
49
|
+
await provider.installDependencies(targetDir);
|
|
50
|
+
spinner.succeed(`Dependencies installed with ${pm}`);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
spinner.warn(`Failed to install dependencies. Run ${chalk.cyan(`${pm} install`)} manually.`);
|
|
54
|
+
}
|
|
55
|
+
// Authenticate via browser; saves to user config (~/.config/terse/auth.json or OS equivalent).
|
|
56
|
+
const loginResult = await loginAndPersist();
|
|
57
|
+
const isAuthenticated = !!loginResult;
|
|
58
|
+
// Connect integrations
|
|
59
|
+
await listAndPromptIntegrations();
|
|
60
|
+
try {
|
|
61
|
+
await generate(provider);
|
|
62
|
+
spinner.succeed(`Generated code`);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
spinner.warn(`Failed to generate code. Run ${chalk.cyan(`$terse generate`)} manually.`);
|
|
66
|
+
}
|
|
67
|
+
console.log(`\n ${chalk.green.bold("Done!")} Your Terse project is ready.\n`);
|
|
68
|
+
console.log(" Next steps:\n");
|
|
69
|
+
let step = 1;
|
|
70
|
+
if (projectName) {
|
|
71
|
+
console.log(` ${step}. cd ${projectName}`);
|
|
72
|
+
step++;
|
|
73
|
+
}
|
|
74
|
+
if (!isAuthenticated) {
|
|
75
|
+
console.log(` ${step}. Run ${chalk.cyan("terse login")} to authenticate`);
|
|
76
|
+
step++;
|
|
77
|
+
}
|
|
78
|
+
console.log(` ${step}. Edit ${provider.entryFile} to define your job`);
|
|
79
|
+
step++;
|
|
80
|
+
const postInitSteps = provider.getPostInitSteps(pm);
|
|
81
|
+
for (const postInitStep of postInitSteps) {
|
|
82
|
+
console.log(` ${step}. ${postInitStep}`);
|
|
83
|
+
step++;
|
|
84
|
+
}
|
|
85
|
+
console.log("");
|
|
86
|
+
}
|
|
87
|
+
function changeDirectory(targetDir) {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
try {
|
|
90
|
+
process.chdir(targetDir);
|
|
91
|
+
resolve();
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
reject(err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrate.d.ts","sourceRoot":"","sources":["../../src/commands/integrate.ts"],"names":[],"mappings":"AAgBA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB/C;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2B/D"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { confirm, input, password, select } from "@inquirer/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import ora from "ora";
|
|
5
|
+
import { INTEGRATION_METADATA, IntegrationType } from "terse-types";
|
|
6
|
+
import { readApiKey, readApiKeyOrBail } from "../api.js";
|
|
7
|
+
import { fetchInstallationUrl, fetchIntegrationFields, fetchIntegrations, pollForConnection, submitIntegrationForm } from "../integrationApi.js";
|
|
8
|
+
import { generate } from "./generate.js";
|
|
9
|
+
export async function integrate() {
|
|
10
|
+
const apiKey = readApiKeyOrBail();
|
|
11
|
+
let didChangeAnyIntegration = false;
|
|
12
|
+
let continueLoop = true;
|
|
13
|
+
while (continueLoop) {
|
|
14
|
+
const result = await connectOneIntegration(apiKey);
|
|
15
|
+
didChangeAnyIntegration = didChangeAnyIntegration || result.status !== "unchanged";
|
|
16
|
+
console.log("");
|
|
17
|
+
continueLoop = await confirm({ message: "Connect another integration?", default: false });
|
|
18
|
+
}
|
|
19
|
+
if (didChangeAnyIntegration) {
|
|
20
|
+
await generate();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function listAndPromptIntegrations() {
|
|
24
|
+
const apiKey = readApiKey();
|
|
25
|
+
if (!apiKey)
|
|
26
|
+
return;
|
|
27
|
+
let integrations;
|
|
28
|
+
try {
|
|
29
|
+
integrations = await fetchIntegrations(apiKey);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
console.error(chalk.red("Failed to fetch integrations"));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const active = integrations.filter(i => i.isActive && i.integrationType !== IntegrationType.TERSE && i.integrationType !== IntegrationType.CRON_JOB);
|
|
36
|
+
if (active.length > 0) {
|
|
37
|
+
console.log("\n Connected integrations:\n");
|
|
38
|
+
for (const i of active) {
|
|
39
|
+
const meta = INTEGRATION_METADATA[i.integrationType];
|
|
40
|
+
console.log(` ${chalk.green("✓")} ${meta?.name || i.integrationType}`);
|
|
41
|
+
}
|
|
42
|
+
console.log("");
|
|
43
|
+
const addMore = await confirm({ message: "Connect another integration?", default: false });
|
|
44
|
+
if (addMore)
|
|
45
|
+
await integrate();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.log(chalk.dim("\n No integrated tools yet.\n"));
|
|
49
|
+
await integrate();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function connectOneIntegration(apiKey) {
|
|
53
|
+
const spinner = ora("Fetching integrations").start();
|
|
54
|
+
let integrations;
|
|
55
|
+
try {
|
|
56
|
+
integrations = await fetchIntegrations(apiKey);
|
|
57
|
+
spinner.stop();
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
spinner.fail("Failed to fetch integrations");
|
|
61
|
+
console.error(chalk.red(` ${err.message}`));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// Filter out system integrations
|
|
65
|
+
const userFacing = integrations.filter(i => i.integrationType !== IntegrationType.TERSE && i.integrationType !== IntegrationType.CRON_JOB);
|
|
66
|
+
if (userFacing.length === 0) {
|
|
67
|
+
console.log(chalk.yellow("\n No integrations available.\n"));
|
|
68
|
+
return { status: "unchanged" };
|
|
69
|
+
}
|
|
70
|
+
const selected = await select({
|
|
71
|
+
message: "Select an integration to connect",
|
|
72
|
+
choices: userFacing.map(i => {
|
|
73
|
+
const meta = INTEGRATION_METADATA[i.integrationType];
|
|
74
|
+
const name = meta?.name || i.integrationType;
|
|
75
|
+
const status = i.isActive ? chalk.green(" ✓ connected") : chalk.dim(" not connected");
|
|
76
|
+
return {
|
|
77
|
+
name: `${name}${status}`,
|
|
78
|
+
value: i.integrationType,
|
|
79
|
+
description: meta?.description
|
|
80
|
+
};
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
const selectedIntegration = userFacing.find(i => i.integrationType === selected);
|
|
84
|
+
// Fetch fields for the selected integration
|
|
85
|
+
const fieldsSpinner = ora("Loading integration details").start();
|
|
86
|
+
let fieldsResponse;
|
|
87
|
+
try {
|
|
88
|
+
fieldsResponse = await fetchIntegrationFields(apiKey, selected);
|
|
89
|
+
fieldsSpinner.stop();
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
fieldsSpinner.fail("Failed to load integration details");
|
|
93
|
+
console.error(chalk.red(` ${err.message}`));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
if (fieldsResponse.installationType === "form") {
|
|
97
|
+
const didUpdate = await handleFormIntegration(apiKey, selected, fieldsResponse.fields);
|
|
98
|
+
return {
|
|
99
|
+
status: didUpdate ? (selectedIntegration?.isActive ? "modified" : "added") : "unchanged",
|
|
100
|
+
integrationType: selected
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
else if (fieldsResponse.installationType === "oauth") {
|
|
104
|
+
const didUpdate = await handleOAuthIntegration(apiKey, selected, fieldsResponse.fields);
|
|
105
|
+
return {
|
|
106
|
+
status: didUpdate ? (selectedIntegration?.isActive ? "modified" : "added") : "unchanged",
|
|
107
|
+
integrationType: selected
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(chalk.yellow(`\n Integration '${selected}' has an unsupported installation type.\n`));
|
|
112
|
+
return {
|
|
113
|
+
status: "unchanged",
|
|
114
|
+
integrationType: selected
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// ─── Form-based integrations (Datadog, PostHog, Snowflake, etc.) ─────────────
|
|
119
|
+
async function handleFormIntegration(apiKey, integrationType, fields) {
|
|
120
|
+
console.log("");
|
|
121
|
+
const formValues = {};
|
|
122
|
+
for (const field of fields) {
|
|
123
|
+
const hint = field.hint ? chalk.dim(` (${field.hint})`) : "";
|
|
124
|
+
if (field.type === "password") {
|
|
125
|
+
formValues[field.name] = await password({
|
|
126
|
+
message: `${field.label}${hint}`,
|
|
127
|
+
validate: field.required ? v => (v.length > 0 ? true : `${field.label} is required`) : undefined
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
formValues[field.name] = await input({
|
|
132
|
+
message: `${field.label}${hint}`,
|
|
133
|
+
default: field.placeholder,
|
|
134
|
+
validate: field.required ? v => (v.length > 0 ? true : `${field.label} is required`) : undefined
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const spinner = ora("Connecting integration").start();
|
|
139
|
+
try {
|
|
140
|
+
const result = await submitIntegrationForm(apiKey, integrationType, formValues);
|
|
141
|
+
if (result.success) {
|
|
142
|
+
spinner.succeed(chalk.green("Integration connected successfully"));
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
spinner.fail(`Failed to connect: ${result.error || "Unknown error"}`);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
spinner.fail("Failed to connect integration");
|
|
152
|
+
console.error(chalk.red(` ${err.message}`));
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ─── OAuth-based integrations (Slack, GitHub, Gmail, etc.) ───────────────────
|
|
157
|
+
async function handleOAuthIntegration(apiKey, integrationType, configFields) {
|
|
158
|
+
// Prompt for configuration fields if any (e.g. Slack's bot vs user choice)
|
|
159
|
+
let options;
|
|
160
|
+
if (configFields.length > 0) {
|
|
161
|
+
console.log("");
|
|
162
|
+
options = {};
|
|
163
|
+
for (const field of configFields) {
|
|
164
|
+
const value = await select({
|
|
165
|
+
message: field.label,
|
|
166
|
+
choices: field.options.map(o => ({ name: o.label, value: o.value }))
|
|
167
|
+
});
|
|
168
|
+
options[field.name] = value;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const spinner = ora("Getting authorization URL").start();
|
|
172
|
+
let installationDetails;
|
|
173
|
+
try {
|
|
174
|
+
installationDetails = await fetchInstallationUrl(apiKey, integrationType, options);
|
|
175
|
+
spinner.stop();
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
spinner.fail("Failed to get authorization URL");
|
|
179
|
+
console.error(chalk.red(` ${err.message}`));
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
console.log(`\n ${chalk.bold("Complete authorization in your browser:")}\n`);
|
|
183
|
+
console.log(` ${chalk.cyan(installationDetails.oauthUrl)}\n`);
|
|
184
|
+
openInBrowser(installationDetails.oauthUrl);
|
|
185
|
+
const pollSpinner = ora("Waiting for authorization to complete").start();
|
|
186
|
+
const connected = await pollForConnection(apiKey, integrationType);
|
|
187
|
+
if (connected) {
|
|
188
|
+
pollSpinner.succeed(chalk.green("Integration connected successfully"));
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
pollSpinner.fail("Authorization timed out — please try again");
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
197
|
+
function openInBrowser(url) {
|
|
198
|
+
try {
|
|
199
|
+
if (process.platform === "darwin") {
|
|
200
|
+
spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
if (process.platform === "win32") {
|
|
204
|
+
spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=integrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrate.js","sourceRoot":"","sources":["../../src/commands/integrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACpE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAqD,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEnM,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAOxC,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAA;IACjC,IAAI,uBAAuB,GAAG,KAAK,CAAA;IAEnC,IAAI,YAAY,GAAG,IAAI,CAAA;IACvB,OAAO,YAAY,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;QAClD,uBAAuB,GAAG,uBAAuB,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,CAAA;QAElF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACf,YAAY,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED,IAAI,uBAAuB,EAAE,CAAC;QAC1B,MAAM,QAAQ,EAAE,CAAA;IACpB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC3C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,IAAI,CAAC,MAAM;QAAE,OAAM;IAEnB,IAAI,YAAY,CAAA;IAChB,IAAI,CAAC;QACD,YAAY,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAA;QACxD,OAAM;IACV,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,eAAe,KAAK,eAAe,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAA;IAEpJ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;QAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,oBAAoB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;YACpD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC,CAAA;QAC3E,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACf,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1F,IAAI,OAAO;YAAE,MAAM,SAAS,EAAE,CAAA;IAClC,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAA;QACxD,MAAM,SAAS,EAAE,CAAA;IACrB,CAAC;AACL,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,MAAc;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,uBAAuB,CAAC,CAAC,KAAK,EAAE,CAAA;IACpD,IAAI,YAAY,CAAA;IAChB,IAAI,CAAC;QACD,YAAY,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAC9C,OAAO,CAAC,IAAI,EAAE,CAAA;IAClB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAA;QAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IAED,iCAAiC;IACjC,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,eAAe,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAA;IAE1I,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kCAAkC,CAAC,CAAC,CAAA;QAC7D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;IAClC,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC1B,OAAO,EAAE,kCAAkC;QAC3C,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACxB,MAAM,IAAI,GAAG,oBAAoB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;YACpD,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,eAAe,CAAA;YAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;YACrF,OAAO;gBACH,IAAI,EAAE,GAAG,IAAI,GAAG,MAAM,EAAE;gBACxB,KAAK,EAAE,CAAC,CAAC,eAAe;gBACxB,WAAW,EAAE,IAAI,EAAE,WAAW;aACjC,CAAA;QACL,CAAC,CAAC;KACL,CAAC,CAAA;IACF,MAAM,mBAAmB,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAA;IAEhF,4CAA4C;IAC5C,MAAM,aAAa,GAAG,GAAG,CAAC,6BAA6B,CAAC,CAAC,KAAK,EAAE,CAAA;IAChE,IAAI,cAAc,CAAA;IAClB,IAAI,CAAC;QACD,cAAc,GAAG,MAAM,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC/D,aAAa,CAAC,IAAI,EAAE,CAAA;IACxB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,aAAa,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;QACxD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IAED,IAAI,cAAc,CAAC,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAA+B,CAAC,CAAA;QAC/G,OAAO;YACH,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW;YACxF,eAAe,EAAE,QAAQ;SAC5B,CAAA;IACL,CAAC;SAAM,IAAI,cAAc,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;QACrD,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAwC,CAAC,CAAA;QACzH,OAAO;YACH,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW;YACxF,eAAe,EAAE,QAAQ;SAC5B,CAAA;IACL,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,QAAQ,2CAA2C,CAAC,CAAC,CAAA;QAClG,OAAO;YACH,MAAM,EAAE,WAAW;YACnB,eAAe,EAAE,QAAQ;SAC5B,CAAA;IACL,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF,KAAK,UAAU,qBAAqB,CAAC,MAAc,EAAE,eAAuB,EAAE,MAA6B;IACvG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAEf,MAAM,UAAU,GAA2B,EAAE,CAAA;IAC7C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE5D,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC5B,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,QAAQ,CAAC;gBACpC,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE;gBAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS;aACnG,CAAC,CAAA;QACN,CAAC;aAAM,CAAC;YACJ,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC;gBACjC,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE;gBAChC,OAAO,EAAE,KAAK,CAAC,WAAW;gBAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS;aACnG,CAAC,CAAA;QACN,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,wBAAwB,CAAC,CAAC,KAAK,EAAE,CAAA;IACrD,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC,CAAA;QAC/E,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;QACf,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAA;YACrE,OAAO,KAAK,CAAA;QAChB,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;QAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC5C,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF,KAAK,UAAU,sBAAsB,CAAC,MAAc,EAAE,eAAuB,EAAE,YAA4C;IACvH,2EAA2E;IAC3E,IAAI,OAA2C,CAAA;IAC/C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACf,OAAO,GAAG,EAAE,CAAA;QACZ,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC;gBACvB,OAAO,EAAE,KAAK,CAAC,KAAK;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;aACvE,CAAC,CAAA;YACF,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;QAC/B,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,2BAA2B,CAAC,CAAC,KAAK,EAAE,CAAA;IACxD,IAAI,mBAAmB,CAAA;IACvB,IAAI,CAAC;QACD,mBAAmB,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;QAClF,OAAO,CAAC,IAAI,EAAE,CAAA;IAClB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAA;QAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC5C,OAAO,KAAK,CAAA;IAChB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,IAAI,CAAC,CAAA;IAC7E,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9D,aAAa,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAA;IAE3C,MAAM,WAAW,GAAG,GAAG,CAAC,uCAAuC,CAAC,CAAC,KAAK,EAAE,CAAA;IACxE,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAElE,IAAI,SAAS,EAAE,CAAC;QACZ,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAA;QACtE,OAAO,IAAI,CAAA;IACf,CAAC;SAAM,CAAC;QACJ,WAAW,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAA;QAC9D,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF,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 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGxE,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,gBAAoC,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { readApiKeyOrBail, resolveEventFromRunId } from "../api.js";
|
|
3
|
+
import { loadJob } from "../loadJob.js";
|
|
4
|
+
import { resolveProvider } from "../providers/resolveProvider.js";
|
|
5
|
+
export async function replay(runId, provider = resolveProvider()) {
|
|
6
|
+
const apiKey = readApiKeyOrBail();
|
|
7
|
+
if (!runId) {
|
|
8
|
+
console.error(chalk.red("Error: --run-id is required.\n"));
|
|
9
|
+
console.error(chalk.dim(" Usage: terse replay --run-id <run-id>"));
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const runHistoryRecord = await resolveEventFromRunId(runId, apiKey);
|
|
13
|
+
if (!runHistoryRecord) {
|
|
14
|
+
console.error(chalk.red("Error: Could not fetch the trigger event for run ${runId}.\n"));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const { job } = await loadJob(provider, runHistoryRecord.agentName);
|
|
18
|
+
await provider.executeJob(job, null, runHistoryRecord.event, { verbose: true });
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAEjE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAa,EAAE,WAA6B,eAAe,EAAE;IACtF,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAA;IAEjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAA;QAC1D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC,CAAA;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACnE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC,CAAA;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAA;IAEnE,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,gBAAgB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;AACnF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGxE,wBAAsB,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,gBAAoC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDrK"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { serializedEventSchema } from "terse-types";
|
|
4
|
+
import { readApiKeyOrBail, readRunId, resolveEventFromRunId } from "../api.js";
|
|
5
|
+
import { loadJob } from "../loadJob.js";
|
|
6
|
+
import { resolveProvider } from "../providers/resolveProvider.js";
|
|
7
|
+
export async function run(jobName, eventJson, eventFile, provider = resolveProvider(), entryFile) {
|
|
8
|
+
if (eventFile && !eventJson) {
|
|
9
|
+
try {
|
|
10
|
+
eventJson = fs.readFileSync(eventFile, "utf-8");
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
console.error(chalk.red(`Error: Could not read event file: ${eventFile}`));
|
|
14
|
+
console.error(chalk.dim(err instanceof Error ? err.message : String(err)));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const apiKey = readApiKeyOrBail({
|
|
19
|
+
title: "Error: Not authenticated.",
|
|
20
|
+
detail: "Run `terse login` to authenticate, or set TERSE_API_KEY in your environment."
|
|
21
|
+
});
|
|
22
|
+
const runId = readRunId();
|
|
23
|
+
let rawEvent;
|
|
24
|
+
if (eventJson) {
|
|
25
|
+
try {
|
|
26
|
+
rawEvent = JSON.parse(eventJson);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(chalk.red("Error: --event must be valid JSON."));
|
|
30
|
+
console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
rawEvent = await resolveEventFromRunId(runId, apiKey);
|
|
36
|
+
}
|
|
37
|
+
if (!rawEvent) {
|
|
38
|
+
console.error(chalk.red("Error: --event <json> or --event-file <path> is required.\n"));
|
|
39
|
+
console.error(chalk.dim(' Usage: terse run --event \'{"integrationType":"...","eventType":"...","formattedContent":"...","debugLog":"...","data":{...}}\''));
|
|
40
|
+
console.error(chalk.dim(" terse run --event-file ./event.json"));
|
|
41
|
+
console.error(chalk.dim(" Tip: Use `terse test` to interactively pick a sample event.\n"));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const { job } = await loadJob(provider, jobName, entryFile);
|
|
45
|
+
let parsed;
|
|
46
|
+
try {
|
|
47
|
+
parsed = serializedEventSchema.parse(rawEvent);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error(chalk.red("Error: --event does not match the canonical Trigger schema."));
|
|
51
|
+
console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
await provider.executeJob(job, runId, parsed, { entryFile });
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGxE,wBAAsB,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAE,gBAAoC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFjJ"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { select } from "@inquirer/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import { IntegrationType } from "terse-sdk";
|
|
5
|
+
import { ApiRoutes, debugTrigger, formatTriggerForAgent } from "terse-types";
|
|
6
|
+
import { fetchWithAuth, readApiKeyOrBail } from "../api.js";
|
|
7
|
+
import { assertProjectRoot } from "../assertProjectRoot.js";
|
|
8
|
+
import { loadJob } from "../loadJob.js";
|
|
9
|
+
import { resolveProvider } from "../providers/resolveProvider.js";
|
|
10
|
+
export async function test(jobName, verbose, provider = resolveProvider(), entryFile) {
|
|
11
|
+
assertProjectRoot(provider);
|
|
12
|
+
const { job } = await loadJob(provider, jobName, entryFile);
|
|
13
|
+
console.log(chalk.cyan(`\n Testing job: ${job.name}\n`));
|
|
14
|
+
const apiKey = readApiKeyOrBail({
|
|
15
|
+
title: "Error: Not authenticated. Unable to fetch sample events.",
|
|
16
|
+
detail: "Run `terse login` to authenticate, or set TERSE_API_KEY in your environment."
|
|
17
|
+
});
|
|
18
|
+
// Split triggers into time-based, webhook, and integration-based
|
|
19
|
+
const timeTriggers = job.triggers.filter(t => t.integrationType === IntegrationType.CRON_JOB);
|
|
20
|
+
const webhookTriggers = job.triggers.filter(t => t.integrationType === IntegrationType.WEBHOOK);
|
|
21
|
+
const integrationTriggers = job.triggers.filter(t => t.integrationType !== IntegrationType.CRON_JOB && t.integrationType !== IntegrationType.WEBHOOK);
|
|
22
|
+
let events = [];
|
|
23
|
+
// Fetch sample events for integration triggers (time triggers have no sample events)
|
|
24
|
+
if (integrationTriggers.length > 0) {
|
|
25
|
+
const spinner = ora("Fetching sample events").start();
|
|
26
|
+
try {
|
|
27
|
+
const result = await fetchWithAuth(ApiRoutes.SDK.SAMPLE_EVENTS, apiKey, {
|
|
28
|
+
triggers: integrationTriggers.map(trigger => ({
|
|
29
|
+
integrationId: trigger.integrationId,
|
|
30
|
+
integrationType: trigger.integrationType,
|
|
31
|
+
config: trigger
|
|
32
|
+
}))
|
|
33
|
+
}, "POST");
|
|
34
|
+
events = result.events;
|
|
35
|
+
spinner.succeed(`Sample events fetched. Found ${events.length} events.`);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
spinner.fail(err instanceof Error ? err.message : "Failed to fetch sample events.");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Add a synthetic manual trigger event for each time trigger
|
|
42
|
+
for (const trigger of timeTriggers) {
|
|
43
|
+
events.push(serializeEvent({
|
|
44
|
+
integrationType: IntegrationType.CRON_JOB,
|
|
45
|
+
eventType: "cron",
|
|
46
|
+
inputId: trigger.integrationId,
|
|
47
|
+
isManualTrigger: true,
|
|
48
|
+
manualContext: `Manual trigger from terse test (schedule: ${trigger.cronExpression ?? "unknown"})`
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
// Add a synthetic manual trigger event for each webhook trigger
|
|
52
|
+
for (const trigger of webhookTriggers) {
|
|
53
|
+
events.push(serializeEvent({
|
|
54
|
+
integrationType: IntegrationType.WEBHOOK,
|
|
55
|
+
eventType: "webhook",
|
|
56
|
+
body: {},
|
|
57
|
+
headers: {},
|
|
58
|
+
method: "POST"
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
if (events.length === 0) {
|
|
62
|
+
console.error(chalk.red("\n No sample events available. Make sure your triggers are configured and events have been received.\n"));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const choice = await select({
|
|
66
|
+
message: "Select sample event:",
|
|
67
|
+
choices: events.map((event, index) => ({
|
|
68
|
+
name: `${event.integrationType} - ${event.debugLog}`,
|
|
69
|
+
value: index
|
|
70
|
+
}))
|
|
71
|
+
});
|
|
72
|
+
await provider.executeJob(job, null, events[choice], { verbose: !!verbose, entryFile });
|
|
73
|
+
}
|
|
74
|
+
function serializeEvent(event) {
|
|
75
|
+
return {
|
|
76
|
+
integrationType: event.integrationType,
|
|
77
|
+
eventType: event.eventType,
|
|
78
|
+
formattedContent: formatTriggerForAgent(event),
|
|
79
|
+
debugLog: debugTrigger(event),
|
|
80
|
+
data: event
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { Command } from "commander";
|
|
4
|
-
import { attach } from "./attach.js";
|
|
5
|
-
import {
|
|
6
|
-
import { deploy } from "./deploy.js";
|
|
7
|
-
import { generate } from "./generate.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { attach } from "./commands/attach.js";
|
|
5
|
+
import { loginAndPersist, logout } from "./commands/auth.js";
|
|
6
|
+
import { deploy } from "./commands/deploy.js";
|
|
7
|
+
import { generate } from "./commands/generate.js";
|
|
8
|
+
import { history } from "./commands/history.js";
|
|
9
|
+
import { init } from "./commands/init.js";
|
|
10
|
+
import { integrate } from "./commands/integrate.js";
|
|
11
|
+
import { replay } from "./commands/replay.js";
|
|
12
|
+
import { run } from "./commands/run.js";
|
|
13
|
+
import { test } from "./commands/test.js";
|
|
10
14
|
import { isPromptCancellationError } from "./promptErrors.js";
|
|
11
15
|
import { resolveProvider } from "./providers/resolveProvider.js";
|
|
12
|
-
import { replay } from "./replay.js";
|
|
13
|
-
import { run } from "./run.js";
|
|
14
|
-
import { test } from "./test.js";
|
|
15
16
|
const program = new Command();
|
|
16
17
|
program.name("terse").description("The Terse CLI — scaffold and manage Terse projects").version("0.1.0");
|
|
17
18
|
program
|
|
@@ -31,12 +32,24 @@ program
|
|
|
31
32
|
});
|
|
32
33
|
program
|
|
33
34
|
.command("login")
|
|
34
|
-
.description("Authenticate with Terse via your browser")
|
|
35
|
+
.description("Authenticate with Terse via your browser (saves credentials to your user config)")
|
|
35
36
|
.action(async () => {
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
37
|
+
const result = await loginAndPersist();
|
|
38
|
+
if (!result)
|
|
38
39
|
process.exit(1);
|
|
39
40
|
});
|
|
41
|
+
program
|
|
42
|
+
.command("logout")
|
|
43
|
+
.description("Remove saved Terse credentials from your user config")
|
|
44
|
+
.action(() => {
|
|
45
|
+
const removed = logout();
|
|
46
|
+
if (removed) {
|
|
47
|
+
console.log(chalk.green(" Logged out."));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.log(chalk.dim(" Not logged in."));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
40
53
|
program
|
|
41
54
|
.command("generate")
|
|
42
55
|
.description("Generate TypeScript types for your connected integrations")
|
|
@@ -82,6 +95,23 @@ program
|
|
|
82
95
|
.action(async (runId) => {
|
|
83
96
|
await replay(runId);
|
|
84
97
|
});
|
|
98
|
+
program
|
|
99
|
+
.command("history")
|
|
100
|
+
.description("View past run events for a job (use --json to pipe into tooling like the Claude Code /improve skill)")
|
|
101
|
+
.argument("[job-name]", "Name of the job to view the history of")
|
|
102
|
+
.option("--json", "Output runs as JSON for machine consumption")
|
|
103
|
+
.option("--limit <n>", "Max runs to fetch (default 20, max 100)", v => parseInt(v, 10))
|
|
104
|
+
.option("--page <n>", "Page number (1-indexed)", v => parseInt(v, 10))
|
|
105
|
+
.option("--status <list>", "Comma-separated statuses (success,failed,cancelled,skipped,in_progress,awaiting_approval)")
|
|
106
|
+
.option("--since <iso>", "Only include runs at or after this ISO timestamp")
|
|
107
|
+
.option("--until <iso>", "Only include runs at or before this ISO timestamp")
|
|
108
|
+
.option("--query <q>", "Free-text search across trigger, decision and event fields")
|
|
109
|
+
.option("--triggers", "Also fetch the input trigger event JSON for each run (cheap, recommended for /improve)")
|
|
110
|
+
.option("--events", "Also fetch the full model event stream for each run (heavy, includes trigger event)")
|
|
111
|
+
.option("--run-id <id>", "Show full chat events for a single run instead of a list")
|
|
112
|
+
.action(async (jobName, opts) => {
|
|
113
|
+
await history(jobName, opts);
|
|
114
|
+
});
|
|
85
115
|
try {
|
|
86
116
|
await program.parseAsync();
|
|
87
117
|
}
|