@orchagent/cli 0.3.27 → 0.3.29
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/commands/agents.js +87 -10
- package/dist/commands/billing.js +122 -0
- package/dist/commands/call.js +83 -53
- package/dist/commands/index.js +8 -0
- package/dist/commands/info.js +56 -3
- package/dist/commands/install.js +64 -5
- package/dist/commands/pricing.js +72 -0
- package/dist/commands/publish.js +71 -0
- package/dist/commands/run.js +50 -21
- package/dist/commands/search.js +15 -0
- package/dist/commands/security.js +344 -0
- package/dist/commands/seller.js +142 -0
- package/dist/commands/skill.js +83 -8
- package/dist/commands/whoami.js +8 -0
- package/dist/commands/workspace.js +0 -1
- package/dist/lib/api.js +41 -0
- package/dist/lib/errors.js +2 -0
- package/dist/lib/output.js +5 -1
- package/dist/lib/pricing.js +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerSellerCommand = registerSellerCommand;
|
|
7
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const open_1 = __importDefault(require("open"));
|
|
10
|
+
const config_1 = require("../lib/config");
|
|
11
|
+
const api_1 = require("../lib/api");
|
|
12
|
+
const api_2 = require("../lib/api");
|
|
13
|
+
const errors_1 = require("../lib/errors");
|
|
14
|
+
const output_1 = require("../lib/output");
|
|
15
|
+
function registerSellerCommand(program) {
|
|
16
|
+
const seller = program
|
|
17
|
+
.command('seller')
|
|
18
|
+
.description('Manage seller account for monetizing your agents');
|
|
19
|
+
// orch seller onboard
|
|
20
|
+
seller
|
|
21
|
+
.command('onboard')
|
|
22
|
+
.description('Start Stripe seller onboarding process')
|
|
23
|
+
.option('--country <code>', 'Country code (default: GB)', 'GB')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
const resolved = await (0, config_1.getResolvedConfig)();
|
|
26
|
+
const country = options.country || 'GB';
|
|
27
|
+
// Create onboarding session
|
|
28
|
+
const response = await (0, api_1.createSellerOnboarding)(resolved, country);
|
|
29
|
+
// Open in browser
|
|
30
|
+
process.stdout.write(`\nOpening Stripe onboarding...\n`);
|
|
31
|
+
process.stdout.write(`Country: ${country}\n\n`);
|
|
32
|
+
await (0, open_1.default)(response.onboarding_url);
|
|
33
|
+
process.stdout.write(chalk_1.default.gray(`If browser doesn't open, visit:\n${response.onboarding_url}\n`));
|
|
34
|
+
});
|
|
35
|
+
// orch seller status
|
|
36
|
+
seller
|
|
37
|
+
.command('status')
|
|
38
|
+
.description('Check seller account status')
|
|
39
|
+
.option('--json', 'Output as JSON')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const resolved = await (0, config_1.getResolvedConfig)();
|
|
42
|
+
const status = await (0, api_1.getSellerStatus)(resolved);
|
|
43
|
+
if (options.json) {
|
|
44
|
+
(0, output_1.printJson)(status);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Display status
|
|
48
|
+
if (!status.onboarded) {
|
|
49
|
+
process.stdout.write(chalk_1.default.yellow('\nNot onboarded\n\n'));
|
|
50
|
+
process.stdout.write('Start selling: orch seller onboard\n');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
process.stdout.write(chalk_1.default.green('\n✓ Onboarded\n\n'));
|
|
54
|
+
if (status.charges_enabled !== undefined) {
|
|
55
|
+
const chargesStatus = status.charges_enabled ? chalk_1.default.green('✓ Enabled') : chalk_1.default.yellow('⚠ Disabled');
|
|
56
|
+
process.stdout.write(`Charges: ${chargesStatus}\n`);
|
|
57
|
+
}
|
|
58
|
+
if (status.payouts_enabled !== undefined) {
|
|
59
|
+
const payoutsStatus = status.payouts_enabled ? chalk_1.default.green('✓ Enabled') : chalk_1.default.yellow('⚠ Disabled');
|
|
60
|
+
process.stdout.write(`Payouts: ${payoutsStatus}\n`);
|
|
61
|
+
}
|
|
62
|
+
if (!status.charges_enabled || !status.payouts_enabled) {
|
|
63
|
+
process.stdout.write(chalk_1.default.gray('\nComplete setup: orch seller dashboard\n'));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// orch seller dashboard
|
|
67
|
+
seller
|
|
68
|
+
.command('dashboard')
|
|
69
|
+
.description('Open Stripe Express dashboard')
|
|
70
|
+
.action(async () => {
|
|
71
|
+
const resolved = await (0, config_1.getResolvedConfig)();
|
|
72
|
+
try {
|
|
73
|
+
const response = await (0, api_1.getSellerDashboardLink)(resolved);
|
|
74
|
+
// Open in browser
|
|
75
|
+
process.stdout.write('\nOpening Stripe dashboard...\n\n');
|
|
76
|
+
await (0, open_1.default)(response.dashboard_url);
|
|
77
|
+
process.stdout.write(chalk_1.default.gray(`If browser doesn't open, visit:\n${response.dashboard_url}\n`));
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (err instanceof api_2.ApiError && (err.status === 404 || err.status === 403)) {
|
|
81
|
+
process.stdout.write(chalk_1.default.yellow('\nNo seller account found\n\n'));
|
|
82
|
+
process.stdout.write('Complete onboarding: orch seller onboard\n');
|
|
83
|
+
process.exit(errors_1.ExitCodes.NOT_FOUND);
|
|
84
|
+
}
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
// orch seller earnings
|
|
89
|
+
seller
|
|
90
|
+
.command('earnings')
|
|
91
|
+
.description('Show earnings from your agents')
|
|
92
|
+
.option('--json', 'Output as JSON')
|
|
93
|
+
.action(async (options) => {
|
|
94
|
+
const resolved = await (0, config_1.getResolvedConfig)();
|
|
95
|
+
const earnings = await (0, api_1.getSellerEarnings)(resolved);
|
|
96
|
+
if (options.json) {
|
|
97
|
+
(0, output_1.printJson)(earnings);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Show total earnings
|
|
101
|
+
const total = earnings.total_earnings_cents / 100;
|
|
102
|
+
process.stdout.write(chalk_1.default.bold(`\nTotal Earnings: ${chalk_1.default.green(`$${total.toFixed(2)} USD`)}\n\n`));
|
|
103
|
+
// Show earnings by agent
|
|
104
|
+
if (earnings.by_agent && earnings.by_agent.length > 0) {
|
|
105
|
+
process.stdout.write(chalk_1.default.bold('Earnings by Agent:\n'));
|
|
106
|
+
const table = new cli_table3_1.default({
|
|
107
|
+
head: [
|
|
108
|
+
chalk_1.default.bold('Agent'),
|
|
109
|
+
chalk_1.default.bold('Calls'),
|
|
110
|
+
chalk_1.default.bold('Earnings'),
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
earnings.by_agent.forEach((item) => {
|
|
114
|
+
const earningsStr = `$${(item.earnings_cents / 100).toFixed(2)}`;
|
|
115
|
+
table.push([item.agent_name, item.calls.toString(), earningsStr]);
|
|
116
|
+
});
|
|
117
|
+
process.stdout.write(`${table.toString()}\n\n`);
|
|
118
|
+
}
|
|
119
|
+
// Show recent transactions
|
|
120
|
+
if (earnings.recent_transactions && earnings.recent_transactions.length > 0) {
|
|
121
|
+
process.stdout.write(chalk_1.default.bold('Recent Transactions:\n'));
|
|
122
|
+
const table = new cli_table3_1.default({
|
|
123
|
+
head: [
|
|
124
|
+
chalk_1.default.bold('Date'),
|
|
125
|
+
chalk_1.default.bold('Agent'),
|
|
126
|
+
chalk_1.default.bold('Sale'),
|
|
127
|
+
chalk_1.default.bold('Your Cut'),
|
|
128
|
+
chalk_1.default.bold('Fee'),
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
earnings.recent_transactions.forEach((tx) => {
|
|
132
|
+
const date = new Date(tx.created_at).toLocaleDateString();
|
|
133
|
+
const sale = `$${(tx.sale_amount_cents / 100).toFixed(2)}`;
|
|
134
|
+
const cut = `$${(tx.earnings_cents / 100).toFixed(2)}`;
|
|
135
|
+
const fee = `$${(tx.fee_cents / 100).toFixed(2)}`;
|
|
136
|
+
table.push([date, tx.agent_name, sale, cut, fee]);
|
|
137
|
+
});
|
|
138
|
+
process.stdout.write(`${table.toString()}\n\n`);
|
|
139
|
+
}
|
|
140
|
+
process.stdout.write(chalk_1.default.gray('Manage payouts: orch seller dashboard\n'));
|
|
141
|
+
});
|
|
142
|
+
}
|
package/dist/commands/skill.js
CHANGED
|
@@ -45,6 +45,7 @@ const api_1 = require("../lib/api");
|
|
|
45
45
|
const errors_1 = require("../lib/errors");
|
|
46
46
|
const analytics_1 = require("../lib/analytics");
|
|
47
47
|
const installed_1 = require("../lib/installed");
|
|
48
|
+
const pricing_1 = require("../lib/pricing");
|
|
48
49
|
const package_json_1 = __importDefault(require("../../package.json"));
|
|
49
50
|
const DEFAULT_VERSION = 'latest';
|
|
50
51
|
/**
|
|
@@ -84,20 +85,94 @@ function parseSkillRef(value) {
|
|
|
84
85
|
throw new errors_1.CliError('Invalid skill reference. Use org/skill or skill format.');
|
|
85
86
|
}
|
|
86
87
|
async function downloadSkillWithFallback(config, org, skill, version) {
|
|
87
|
-
//
|
|
88
|
+
// Fetch metadata first to check if paid
|
|
89
|
+
let skillMeta;
|
|
88
90
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
skillMeta = await (0, api_1.getPublicAgent)(config, org, skill, version);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
// If 404, might be private skill - will handle below
|
|
95
|
+
if (err instanceof api_1.ApiError && err.status === 404) {
|
|
96
|
+
skillMeta = null;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Verify it's a skill type before proceeding
|
|
103
|
+
if (skillMeta) {
|
|
104
|
+
const skillType = skillMeta.type;
|
|
92
105
|
if (skillType !== 'skill') {
|
|
93
106
|
throw new errors_1.CliError(`${org}/${skill} is not a skill (type: ${skillType || 'prompt'})`);
|
|
94
107
|
}
|
|
95
|
-
// Download content from public endpoint
|
|
96
|
-
return await (0, api_1.publicRequest)(config, `/public/agents/${org}/${skill}/${version}/download`);
|
|
97
108
|
}
|
|
98
|
-
|
|
99
|
-
|
|
109
|
+
// Check if paid skill BEFORE attempting download
|
|
110
|
+
if (skillMeta && (0, pricing_1.isPaidAgent)(skillMeta)) {
|
|
111
|
+
// Paid skill - check ownership
|
|
112
|
+
if (config.apiKey) {
|
|
113
|
+
const callerOrg = await (0, api_1.getOrg)(config);
|
|
114
|
+
const isOwner = (skillMeta.org_id && callerOrg.id === skillMeta.org_id) ||
|
|
115
|
+
(skillMeta.org_slug && callerOrg.slug === skillMeta.org_slug);
|
|
116
|
+
if (isOwner) {
|
|
117
|
+
// Owner - fetch from authenticated endpoint with full content
|
|
118
|
+
const myAgents = await (0, api_1.listMyAgents)(config);
|
|
119
|
+
const matching = myAgents.filter(a => a.name === skill && a.type === 'skill');
|
|
120
|
+
if (matching.length > 0) {
|
|
121
|
+
let targetAgent;
|
|
122
|
+
if (version === 'latest') {
|
|
123
|
+
targetAgent = matching.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const found = matching.find(a => a.version === version);
|
|
127
|
+
if (!found) {
|
|
128
|
+
throw new api_1.ApiError(`Skill '${org}/${skill}@${version}' not found`, 404);
|
|
129
|
+
}
|
|
130
|
+
targetAgent = found;
|
|
131
|
+
}
|
|
132
|
+
// Fetch full skill data with prompt from authenticated endpoint
|
|
133
|
+
const skillData = await (0, api_1.request)(config, 'GET', `/agents/${targetAgent.id}`);
|
|
134
|
+
// Convert Agent to SkillDownload format
|
|
135
|
+
return {
|
|
136
|
+
type: skillData.type,
|
|
137
|
+
name: skillData.name,
|
|
138
|
+
version: skillData.version,
|
|
139
|
+
description: skillData.description,
|
|
140
|
+
prompt: skillData.prompt,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Non-owner - block with helpful message
|
|
146
|
+
const price = (0, pricing_1.formatPrice)(skillMeta);
|
|
147
|
+
throw new errors_1.CliError(`This skill is paid (${price}) and can only be used on the server.\n\n` +
|
|
148
|
+
`Paid skills are loaded automatically during server execution.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Not authenticated - block
|
|
153
|
+
const price = (0, pricing_1.formatPrice)(skillMeta);
|
|
154
|
+
throw new errors_1.CliError(`This skill is paid (${price}) and can only be used on the server.\n\n` +
|
|
155
|
+
`Paid skills are loaded automatically during server execution.`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Free skill or public metadata available - proceed with normal download
|
|
159
|
+
if (skillMeta) {
|
|
160
|
+
try {
|
|
161
|
+
return await (0, api_1.publicRequest)(config, `/public/agents/${org}/${skill}/${version}/download`);
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
// If download fails but metadata exists, it might be a 403 for other reasons
|
|
165
|
+
if (err instanceof api_1.ApiError && err.status === 403) {
|
|
166
|
+
const payload = err.payload;
|
|
167
|
+
if (payload?.error?.code === 'PAID_AGENT_SERVER_ONLY') {
|
|
168
|
+
// Legacy error handling (shouldn't reach here with new logic)
|
|
169
|
+
const price = payload.error.price_per_call_cents || 0;
|
|
170
|
+
throw new errors_1.CliError(`This skill costs $${(price / 100).toFixed(2)}/call and runs on server only.\n\n` +
|
|
171
|
+
`Use: orch call ${org}/${skill}@${version} --input '{...}'`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
100
174
|
throw err;
|
|
175
|
+
}
|
|
101
176
|
}
|
|
102
177
|
// Fallback to authenticated endpoint for private skills
|
|
103
178
|
if (!config.apiKey) {
|
package/dist/commands/whoami.js
CHANGED
|
@@ -13,5 +13,13 @@ function registerWhoamiCommand(program) {
|
|
|
13
13
|
process.stdout.write(`Logged in as: ${org.name}\n`);
|
|
14
14
|
process.stdout.write(`Org slug: ${org.slug}\n`);
|
|
15
15
|
process.stdout.write(`API URL: ${config.apiUrl}\n`);
|
|
16
|
+
// Show balance after org info
|
|
17
|
+
try {
|
|
18
|
+
const balance = await (0, api_1.getCreditsBalance)(config);
|
|
19
|
+
process.stdout.write(`Credits: $${(balance.balance_cents / 100).toFixed(2)} USD\n`);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Ignore errors - don't let balance check break whoami
|
|
23
|
+
}
|
|
16
24
|
});
|
|
17
25
|
}
|
|
@@ -85,7 +85,6 @@ async function useWorkspace(slug) {
|
|
|
85
85
|
// Save to config
|
|
86
86
|
const configFile = await (0, config_1.loadConfig)();
|
|
87
87
|
configFile.workspace = slug;
|
|
88
|
-
delete configFile.workspace_confirmed;
|
|
89
88
|
await (0, config_1.saveConfig)(configFile);
|
|
90
89
|
await (0, analytics_1.track)('cli_workspace_use', { slug });
|
|
91
90
|
process.stdout.write(chalk_1.default.green('\u2713') + ` Now using workspace: ${workspace.name} (${workspace.slug})\n`);
|
package/dist/lib/api.js
CHANGED
|
@@ -64,6 +64,13 @@ exports.getEnvironment = getEnvironment;
|
|
|
64
64
|
exports.createEnvironment = createEnvironment;
|
|
65
65
|
exports.deleteEnvironment = deleteEnvironment;
|
|
66
66
|
exports.setWorkspaceDefaultEnvironment = setWorkspaceDefaultEnvironment;
|
|
67
|
+
exports.getCreditsBalance = getCreditsBalance;
|
|
68
|
+
exports.createCreditCheckout = createCreditCheckout;
|
|
69
|
+
exports.getSellerStatus = getSellerStatus;
|
|
70
|
+
exports.createSellerOnboarding = createSellerOnboarding;
|
|
71
|
+
exports.getSellerDashboardLink = getSellerDashboardLink;
|
|
72
|
+
exports.getSellerEarnings = getSellerEarnings;
|
|
73
|
+
exports.setAgentPricing = setAgentPricing;
|
|
67
74
|
const errors_1 = require("./errors");
|
|
68
75
|
const DEFAULT_TIMEOUT_MS = 15000;
|
|
69
76
|
const CALL_TIMEOUT_MS = 120000; // 2 minutes for agent calls (can take time)
|
|
@@ -447,3 +454,37 @@ async function setWorkspaceDefaultEnvironment(config, workspaceId, environmentId
|
|
|
447
454
|
headers: { 'Content-Type': 'application/json' },
|
|
448
455
|
});
|
|
449
456
|
}
|
|
457
|
+
// Billing API functions
|
|
458
|
+
async function getCreditsBalance(config) {
|
|
459
|
+
return request(config, 'GET', '/billing/credits');
|
|
460
|
+
}
|
|
461
|
+
async function createCreditCheckout(config, amountCents) {
|
|
462
|
+
return request(config, 'POST', '/billing/add-credits', {
|
|
463
|
+
body: JSON.stringify({ amount_cents: amountCents }),
|
|
464
|
+
headers: { 'Content-Type': 'application/json' },
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
async function getSellerStatus(config) {
|
|
468
|
+
return request(config, 'GET', '/sellers/status');
|
|
469
|
+
}
|
|
470
|
+
async function createSellerOnboarding(config, country) {
|
|
471
|
+
return request(config, 'POST', '/sellers/onboard', {
|
|
472
|
+
body: JSON.stringify({ country }),
|
|
473
|
+
headers: { 'Content-Type': 'application/json' },
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
async function getSellerDashboardLink(config) {
|
|
477
|
+
return request(config, 'POST', '/sellers/dashboard-link');
|
|
478
|
+
}
|
|
479
|
+
async function getSellerEarnings(config) {
|
|
480
|
+
return request(config, 'GET', '/billing/earnings');
|
|
481
|
+
}
|
|
482
|
+
async function setAgentPricing(config, agentId, pricingMode, pricePerCallCents) {
|
|
483
|
+
return request(config, 'PUT', `/agents/${agentId}/pricing`, {
|
|
484
|
+
body: JSON.stringify({
|
|
485
|
+
pricing_mode: pricingMode,
|
|
486
|
+
price_per_call_cents: pricePerCallCents,
|
|
487
|
+
}),
|
|
488
|
+
headers: { 'Content-Type': 'application/json' },
|
|
489
|
+
});
|
|
490
|
+
}
|
package/dist/lib/errors.js
CHANGED
|
@@ -99,6 +99,8 @@ exports.ExitCodes = {
|
|
|
99
99
|
function mapHttpStatusToExitCode(status) {
|
|
100
100
|
if (status === 401)
|
|
101
101
|
return exports.ExitCodes.AUTH_ERROR;
|
|
102
|
+
if (status === 402)
|
|
103
|
+
return exports.ExitCodes.PERMISSION_DENIED; // Payment required
|
|
102
104
|
if (status === 403)
|
|
103
105
|
return exports.ExitCodes.PERMISSION_DENIED;
|
|
104
106
|
if (status === 404)
|
package/dist/lib/output.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.printJson = printJson;
|
|
|
7
7
|
exports.printAgentsTable = printAgentsTable;
|
|
8
8
|
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const pricing_1 = require("./pricing");
|
|
10
11
|
function printJson(value) {
|
|
11
12
|
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
12
13
|
}
|
|
@@ -17,6 +18,7 @@ function printAgentsTable(agents) {
|
|
|
17
18
|
chalk_1.default.bold('Type'),
|
|
18
19
|
chalk_1.default.bold('Providers'),
|
|
19
20
|
chalk_1.default.bold('Stars'),
|
|
21
|
+
chalk_1.default.bold('Price'),
|
|
20
22
|
chalk_1.default.bold('Description'),
|
|
21
23
|
],
|
|
22
24
|
});
|
|
@@ -25,12 +27,14 @@ function printAgentsTable(agents) {
|
|
|
25
27
|
const type = agent.type || 'code';
|
|
26
28
|
const providers = formatProviders(agent.supported_providers);
|
|
27
29
|
const stars = agent.stars_count ?? 0;
|
|
30
|
+
const price = (0, pricing_1.formatPrice)(agent);
|
|
31
|
+
const priceColored = (0, pricing_1.isPaidAgent)(agent) ? chalk_1.default.yellow(price) : chalk_1.default.green(price);
|
|
28
32
|
const desc = agent.description
|
|
29
33
|
? agent.description.length > 30
|
|
30
34
|
? agent.description.slice(0, 27) + '...'
|
|
31
35
|
: agent.description
|
|
32
36
|
: '-';
|
|
33
|
-
table.push([fullName, type, providers, stars.toString(), desc]);
|
|
37
|
+
table.push([fullName, type, providers, stars.toString(), priceColored, desc]);
|
|
34
38
|
});
|
|
35
39
|
process.stdout.write(`${table.toString()}\n`);
|
|
36
40
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPaidAgent = isPaidAgent;
|
|
4
|
+
exports.formatPrice = formatPrice;
|
|
5
|
+
function isPaidAgent(agent) {
|
|
6
|
+
// Fail-closed: per_call mode with missing or >0 price is paid
|
|
7
|
+
if (agent.pricing_mode === 'per_call') {
|
|
8
|
+
const price = agent.price_per_call_cents;
|
|
9
|
+
return price === null || price === undefined || price > 0;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
function formatPrice(agent) {
|
|
14
|
+
if (!isPaidAgent(agent)) {
|
|
15
|
+
return 'FREE';
|
|
16
|
+
}
|
|
17
|
+
const price = agent.price_per_call_cents;
|
|
18
|
+
if (!price) {
|
|
19
|
+
return 'PAID (server-only)'; // Fail-closed message
|
|
20
|
+
}
|
|
21
|
+
return `$${(price / 100).toFixed(2)}/call`;
|
|
22
|
+
}
|