@skrr-ai/cli 0.1.117 → 0.1.119
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/base-command.d.ts +1 -0
- package/dist/base-command.js +7 -1
- package/dist/commands/actions/browse.js +2 -1
- package/dist/commands/actions/install.d.ts +1 -0
- package/dist/commands/actions/install.js +21 -1
- package/dist/commands/actions/list.js +2 -1
- package/dist/commands/actions/show.js +2 -1
- package/dist/commands/memory/versions/list.d.ts +2 -0
- package/dist/commands/memory/versions/list.js +3 -2
- package/dist/commands/memory/versions/show.d.ts +2 -0
- package/dist/commands/memory/versions/show.js +3 -2
- package/dist/commands/skills/browse.js +2 -1
- package/dist/commands/skills/details.js +4 -2
- package/dist/commands/skills/featured.js +2 -1
- package/dist/commands/skills/install.d.ts +1 -0
- package/dist/commands/skills/install.js +21 -1
- package/dist/commands/skills/search.js +2 -1
- package/dist/commands/store/acquisitions/list.js +2 -1
- package/dist/commands/store/acquisitions/show.js +2 -1
- package/dist/commands/store/browse.js +4 -2
- package/dist/commands/store/install.d.ts +1 -0
- package/dist/commands/store/install.js +26 -2
- package/dist/commands/store/releases.js +4 -2
- package/dist/commands/store/show.js +3 -2
- package/dist/commands/store/tip.js +2 -2
- package/dist/generated/agent-guides.json +63 -41
- package/dist/lib/action-listings.js +2 -1
- package/dist/lib/api-fetch.d.ts +4 -0
- package/dist/lib/api-fetch.js +26 -6
- package/dist/lib/memory-history-session.d.ts +14 -0
- package/dist/lib/memory-history-session.js +60 -0
- package/dist/lib/node-adapter.js +4 -3
- package/dist/lib/scoped-memory-command.d.ts +6 -0
- package/dist/lib/scoped-memory-command.js +34 -3
- package/dist/lib/store-listing.d.ts +6 -1
- package/dist/lib/store-listing.js +6 -1
- package/dist/lib/task-admission.js +27 -5
- package/dist/lib/task-runtime-headers.d.ts +11 -0
- package/dist/lib/task-runtime-headers.js +83 -0
- package/dist/lib/task-write-attribution.js +1 -1
- package/dist/lib/usd-micros.d.ts +27 -0
- package/dist/lib/usd-micros.js +67 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.d.ts +17 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.js +35 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.d.ts +17 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.js +44 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +11587 -11548
- package/oclif.manifest.json +28 -2
- package/package.json +1 -1
package/dist/base-command.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export declare abstract class BaseCommand extends Command {
|
|
|
32
32
|
* acquiring unrelated account authority. Human invocations are unaffected.
|
|
33
33
|
*/
|
|
34
34
|
static autonomousCredentialPolicy: 'delegated' | 'bound-session';
|
|
35
|
+
static sessionReadPolicy?: 'memory-history-v1';
|
|
35
36
|
/** Add the owning agent's web detail link without overwriting resource URLs. */
|
|
36
37
|
protected withAgentContext<T>(agentId: string, value: T): T & {
|
|
37
38
|
agentUrl: string | null;
|
package/dist/base-command.js
CHANGED
|
@@ -53,6 +53,7 @@ const cli_id_1 = require("./lib/cli-id");
|
|
|
53
53
|
const keychain_2 = require("./lib/keychain");
|
|
54
54
|
const outbox_1 = require("./lib/outbox");
|
|
55
55
|
const node_adapter_1 = require("./lib/node-adapter");
|
|
56
|
+
const memory_history_session_1 = require("./lib/memory-history-session");
|
|
56
57
|
const migrate_1 = require("./lib/migrate");
|
|
57
58
|
const auth_core_init_1 = require("./lib/auth-core-init");
|
|
58
59
|
const credential_resolver_1 = require("./lib/credential-resolver");
|
|
@@ -125,6 +126,7 @@ class BaseCommand extends core_1.Command {
|
|
|
125
126
|
* acquiring unrelated account authority. Human invocations are unaffected.
|
|
126
127
|
*/
|
|
127
128
|
static autonomousCredentialPolicy = 'delegated';
|
|
129
|
+
static sessionReadPolicy;
|
|
128
130
|
/** Add the owning agent's web detail link without overwriting resource URLs. */
|
|
129
131
|
withAgentContext(agentId, value) {
|
|
130
132
|
const agentUrl = (0, web_url_1.agentUrlFrom)(this.cliConfig.baseURL, { id: agentId });
|
|
@@ -292,7 +294,11 @@ class BaseCommand extends core_1.Command {
|
|
|
292
294
|
// touching migration, Keychain/file auth, refresh, or daemon auto-broker
|
|
293
295
|
// state. The restricted session token (or a null credential when it is
|
|
294
296
|
// missing) is the only adapter authority exposed to the command.
|
|
295
|
-
|
|
297
|
+
const historySession = this.constructor.sessionReadPolicy === 'memory-history-v1' &&
|
|
298
|
+
(0, memory_history_session_1.hasMemoryHistoryRuntime)() ? (0, memory_history_session_1.memoryHistorySession)() : null;
|
|
299
|
+
let autonomousCredential = historySession
|
|
300
|
+
? { token: historySession.token, source: 'env-token', kind: (0, auth_core_1.classifyTokenKind)(historySession.token) }
|
|
301
|
+
: (0, credential_resolver_1.resolveTrustedAutonomousCredential)();
|
|
296
302
|
const boundSessionCommand = Boolean(autonomousCredential &&
|
|
297
303
|
this.constructor.autonomousCredentialPolicy === 'bound-session');
|
|
298
304
|
if ((0, delegated_cli_1.isDelegatedCliSession)() && !boundSessionCommand) {
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const action_listings_1 = require("../../lib/action-listings");
|
|
7
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
7
8
|
class ActionsBrowse extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'Browse public agent-action marketplace listings';
|
|
9
10
|
static examples = [
|
|
@@ -39,7 +40,7 @@ class ActionsBrowse extends base_command_1.BaseCommand {
|
|
|
39
40
|
this.handleApiError(err);
|
|
40
41
|
}
|
|
41
42
|
if (flags.json) {
|
|
42
|
-
this.log(JSON.stringify(response, null, 2));
|
|
43
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
(0, action_listings_1.renderActionListings)(response.data, (line) => this.log(line));
|
|
@@ -9,6 +9,7 @@ export default class ActionsInstall extends BaseCommand {
|
|
|
9
9
|
agent: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
'expected-price': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
13
|
};
|
|
13
14
|
run(): Promise<void>;
|
|
14
15
|
}
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const prompt_1 = require("../../lib/prompt");
|
|
7
7
|
const agent_actions_1 = require("../../lib/agent-actions");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
class ActionsInstall extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Install an action listing into an agent. A paid listing shows its price and asks you to confirm first.';
|
|
10
11
|
static examples = [
|
|
@@ -22,6 +23,10 @@ class ActionsInstall extends base_command_1.BaseCommand {
|
|
|
22
23
|
char: 'y',
|
|
23
24
|
description: 'Confirm a paid install without prompting. The price is still printed.',
|
|
24
25
|
}),
|
|
26
|
+
'expected-price': core_1.Flags.string({
|
|
27
|
+
description: 'Refuse unless the install would charge exactly this USD amount (e.g. 4 or 2.50; 0 pins free). ' +
|
|
28
|
+
'Use it to pin the price the person named, not just the one read now.',
|
|
29
|
+
}),
|
|
25
30
|
};
|
|
26
31
|
async run() {
|
|
27
32
|
this.requireAuth();
|
|
@@ -44,6 +49,21 @@ class ActionsInstall extends base_command_1.BaseCommand {
|
|
|
44
49
|
// server would actually charge, not the sticker price.
|
|
45
50
|
charge = 0;
|
|
46
51
|
}
|
|
52
|
+
// A caller-pinned price binds the install to what the PERSON named, not
|
|
53
|
+
// just to what this command read (OSK-18256 — same convention as
|
|
54
|
+
// `store install`).
|
|
55
|
+
const expectedMicros = (0, usd_micros_1.expectedPriceFlagMicros)(flags['expected-price']);
|
|
56
|
+
if (expectedMicros === null) {
|
|
57
|
+
this.error(`--expected-price must be a USD amount with at most 2 decimals, e.g. 4 or 2.50 (got "${flags['expected-price']}")`, { exit: 2 });
|
|
58
|
+
}
|
|
59
|
+
if (expectedMicros !== undefined && expectedMicros !== charge) {
|
|
60
|
+
this.failWithCliError({
|
|
61
|
+
message: (0, usd_micros_1.expectedPriceMismatchMessage)(expectedMicros, charge),
|
|
62
|
+
code: 'EXPECTED_PRICE_MISMATCH',
|
|
63
|
+
exit: 1,
|
|
64
|
+
retryable: false,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
47
67
|
if (charge > 0) {
|
|
48
68
|
const name = listing.displayName || listing.name || args.id;
|
|
49
69
|
// Printed before any prompt and even with --yes, so a scripted purchase
|
|
@@ -76,7 +96,7 @@ class ActionsInstall extends base_command_1.BaseCommand {
|
|
|
76
96
|
this.handleApiError(err);
|
|
77
97
|
}
|
|
78
98
|
if (flags.json) {
|
|
79
|
-
this.log(JSON.stringify(response, null, 2));
|
|
99
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
80
100
|
return;
|
|
81
101
|
}
|
|
82
102
|
this.log(response.alreadyInstalled
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
7
|
const action_listings_1 = require("../../lib/action-listings");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
class ActionsList extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'List your agent-action marketplace listings';
|
|
10
11
|
static examples = [
|
|
@@ -39,7 +40,7 @@ class ActionsList extends base_command_1.BaseCommand {
|
|
|
39
40
|
this.handleApiError(err);
|
|
40
41
|
}
|
|
41
42
|
if (flags.json) {
|
|
42
|
-
this.printJsonResult((0, list_output_1.listResult)(response));
|
|
43
|
+
this.printJsonResult((0, list_output_1.listResult)((0, usd_micros_1.withUsdPrices)(response)));
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
(0, action_listings_1.renderActionListings)(response.data, (line) => this.log(line));
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const action_listings_1 = require("../../lib/action-listings");
|
|
7
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
7
8
|
class ActionsShow extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'Show an agent-action marketplace listing';
|
|
9
10
|
static examples = [
|
|
@@ -27,7 +28,7 @@ class ActionsShow extends base_command_1.BaseCommand {
|
|
|
27
28
|
this.handleApiError(err);
|
|
28
29
|
}
|
|
29
30
|
if (flags.json) {
|
|
30
|
-
this.log(JSON.stringify(listing, null, 2));
|
|
31
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(listing), null, 2));
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
34
|
(0, action_listings_1.renderActionListing)(listing, (line) => this.log(line));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ScopedMemoryCommand } from '../../../lib/scoped-memory-command';
|
|
2
2
|
export default class MemoryVersionsList extends ScopedMemoryCommand {
|
|
3
|
+
static autonomousCredentialPolicy: "bound-session";
|
|
4
|
+
static sessionReadPolicy: "memory-history-v1";
|
|
3
5
|
static description: string;
|
|
4
6
|
static args: {
|
|
5
7
|
memory: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -4,14 +4,15 @@ const list_output_1 = require("../../../lib/list-output");
|
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
5
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
6
6
|
class MemoryVersionsList extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
7
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
8
|
+
static sessionReadPolicy = 'memory-history-v1';
|
|
7
9
|
static description = 'List immutable versions for one Memory topic';
|
|
8
10
|
static args = { memory: core_1.Args.string({ required: true, ignoreStdin: true }) };
|
|
9
11
|
static flags = { ...scoped_memory_command_1.scopedMemoryFlags, limit: core_1.Flags.integer({ default: 100 }) };
|
|
10
12
|
async run() {
|
|
11
13
|
this.requireAuth();
|
|
12
14
|
const { args, flags } = await this.parse(MemoryVersionsList);
|
|
13
|
-
const
|
|
14
|
-
const result = await this.memoryApi(flags.agent, `/stores/${store.id}/versions${this.query(flags, { memoryId: args.memory, limit: flags.limit })}`);
|
|
15
|
+
const result = await this.memoryHistoryApi(flags, { memoryId: args.memory, limit: flags.limit });
|
|
15
16
|
if (flags.json)
|
|
16
17
|
return this.printJsonResult((0, list_output_1.listResult)(result, 'versions'));
|
|
17
18
|
for (const version of result.versions)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ScopedMemoryCommand } from '../../../lib/scoped-memory-command';
|
|
2
2
|
export default class MemoryVersionsShow extends ScopedMemoryCommand {
|
|
3
|
+
static autonomousCredentialPolicy: "bound-session";
|
|
4
|
+
static sessionReadPolicy: "memory-history-v1";
|
|
3
5
|
static description: string;
|
|
4
6
|
static args: {
|
|
5
7
|
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -3,14 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
5
5
|
class MemoryVersionsShow extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
6
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
7
|
+
static sessionReadPolicy = 'memory-history-v1';
|
|
6
8
|
static description = 'Show one immutable MemoryVersion';
|
|
7
9
|
static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
|
|
8
10
|
static flags = scoped_memory_command_1.scopedMemoryFlags;
|
|
9
11
|
async run() {
|
|
10
12
|
this.requireAuth();
|
|
11
13
|
const { args, flags } = await this.parse(MemoryVersionsShow);
|
|
12
|
-
const
|
|
13
|
-
const result = await this.memoryApi(flags.agent, `/stores/${store.id}/versions/${encodeURIComponent(args.id)}${this.query(flags)}`);
|
|
14
|
+
const result = await this.memoryHistoryApi(flags, { versionId: args.id });
|
|
14
15
|
this.print(result, flags.json, `${result.id} ${result.operation}\n${JSON.stringify(result.payloadSnapshot, null, 2)}`);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
@@ -6,6 +6,7 @@ const core_1 = require("@oclif/core");
|
|
|
6
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
8
|
const format_1 = require("../../lib/format");
|
|
9
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
9
10
|
function skillBrowseDescription(skill) {
|
|
10
11
|
const description = String(skill.description ?? '').trim();
|
|
11
12
|
if (description && description !== '>' && description !== '|')
|
|
@@ -64,7 +65,7 @@ class SkillsBrowse extends base_command_1.BaseCommand {
|
|
|
64
65
|
this.handleApiError(err);
|
|
65
66
|
}
|
|
66
67
|
if (flags.json) {
|
|
67
|
-
this.log(JSON.stringify(response, null, 2));
|
|
68
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
71
|
const r = response;
|
|
@@ -4,6 +4,8 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const local_skills_1 = require("../../lib/local-skills");
|
|
7
|
+
const store_listing_1 = require("../../lib/store-listing");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
7
9
|
class SkillsDetails extends base_command_1.BaseCommand {
|
|
8
10
|
static description = 'Show full details for a skill';
|
|
9
11
|
static examples = [
|
|
@@ -49,7 +51,7 @@ class SkillsDetails extends base_command_1.BaseCommand {
|
|
|
49
51
|
await this.failOnStoreMiss(err, args.id);
|
|
50
52
|
}
|
|
51
53
|
if (flags.json) {
|
|
52
|
-
this.log(JSON.stringify(skill, null, 2));
|
|
54
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(skill), null, 2));
|
|
53
55
|
return;
|
|
54
56
|
}
|
|
55
57
|
const s = skill;
|
|
@@ -59,7 +61,7 @@ class SkillsDetails extends base_command_1.BaseCommand {
|
|
|
59
61
|
this.log(`Author: ${s.authorName ?? s.author ?? '-'}`);
|
|
60
62
|
this.log(`Rating: ${s.rating != null ? s.rating.toFixed(1) : '-'} (${s.ratingCount ?? 0} reviews)`);
|
|
61
63
|
this.log(`Installs: ${s.installCount ?? 0}`);
|
|
62
|
-
this.log(`Price: ${s.price ?
|
|
64
|
+
this.log(`Price: ${(0, store_listing_1.formatListingPrice)(typeof s.price === 'number' ? s.price : null)}`);
|
|
63
65
|
this.log(`Public: ${s.isPublic ? 'yes' : 'no'}`);
|
|
64
66
|
this.log(`Created: ${s.createdAt ?? '-'}`);
|
|
65
67
|
if (s.description) {
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
7
|
const format_1 = require("../../lib/format");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
const browse_1 = require("./browse");
|
|
9
10
|
function featuredSkillIndex(response, limit) {
|
|
10
11
|
const envelope = response;
|
|
@@ -41,7 +42,7 @@ class SkillsFeatured extends base_command_1.BaseCommand {
|
|
|
41
42
|
}
|
|
42
43
|
const index = featuredSkillIndex(response, flags.limit);
|
|
43
44
|
if (flags.json)
|
|
44
|
-
return void this.log(JSON.stringify(index, null, 2));
|
|
45
|
+
return void this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(index), null, 2));
|
|
45
46
|
const items = index.data;
|
|
46
47
|
if (items.length === 0) {
|
|
47
48
|
this.log('No featured skills.');
|
|
@@ -10,6 +10,7 @@ export default class SkillsInstall extends BaseCommand {
|
|
|
10
10
|
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
service: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
'expected-price': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
14
|
};
|
|
14
15
|
/** A store 404 for a name that may be a skill on the caller's machine. */
|
|
15
16
|
private failOnStoreMiss;
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const prompt_1 = require("../../lib/prompt");
|
|
7
7
|
const local_skills_1 = require("../../lib/local-skills");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
class SkillsInstall extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Install a skill from the store to a service (agent). A paid skill shows its price and asks you to confirm first.';
|
|
10
11
|
static examples = [
|
|
@@ -31,6 +32,10 @@ class SkillsInstall extends base_command_1.BaseCommand {
|
|
|
31
32
|
char: 'y',
|
|
32
33
|
description: 'Confirm a paid install without prompting. The price is still printed.',
|
|
33
34
|
}),
|
|
35
|
+
'expected-price': core_1.Flags.string({
|
|
36
|
+
description: 'Refuse unless the install would charge exactly this USD amount (e.g. 4 or 2.50; 0 pins free). ' +
|
|
37
|
+
'Use it to pin the price the person named, not just the one read now.',
|
|
38
|
+
}),
|
|
34
39
|
};
|
|
35
40
|
/** A store 404 for a name that may be a skill on the caller's machine. */
|
|
36
41
|
async failOnStoreMiss(err, id) {
|
|
@@ -74,6 +79,21 @@ class SkillsInstall extends base_command_1.BaseCommand {
|
|
|
74
79
|
return await this.failOnStoreMiss(err, args.id);
|
|
75
80
|
}
|
|
76
81
|
const charge = Number(listing.price) || 0;
|
|
82
|
+
// A caller-pinned price binds the install to what the PERSON named, not
|
|
83
|
+
// just to what this command read (OSK-18256 — same convention as
|
|
84
|
+
// `store install`).
|
|
85
|
+
const expectedMicros = (0, usd_micros_1.expectedPriceFlagMicros)(flags['expected-price']);
|
|
86
|
+
if (expectedMicros === null) {
|
|
87
|
+
this.error(`--expected-price must be a USD amount with at most 2 decimals, e.g. 4 or 2.50 (got "${flags['expected-price']}")`, { exit: 2 });
|
|
88
|
+
}
|
|
89
|
+
if (expectedMicros !== undefined && expectedMicros !== charge) {
|
|
90
|
+
this.failWithCliError({
|
|
91
|
+
message: (0, usd_micros_1.expectedPriceMismatchMessage)(expectedMicros, charge),
|
|
92
|
+
code: 'EXPECTED_PRICE_MISMATCH',
|
|
93
|
+
exit: 1,
|
|
94
|
+
retryable: false,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
77
97
|
if (charge > 0) {
|
|
78
98
|
const name = listing.displayName || listing.name || args.id;
|
|
79
99
|
// Printed before any prompt and even with --yes, so a scripted purchase
|
|
@@ -106,7 +126,7 @@ class SkillsInstall extends base_command_1.BaseCommand {
|
|
|
106
126
|
return await this.failOnStoreMiss(err, args.id);
|
|
107
127
|
}
|
|
108
128
|
if (flags.json) {
|
|
109
|
-
this.log(JSON.stringify(result, null, 2));
|
|
129
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(result), null, 2));
|
|
110
130
|
return;
|
|
111
131
|
}
|
|
112
132
|
const r = result;
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
7
|
const search_query_1 = require("../../lib/search-query");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
class SkillsSearch extends base_command_1.BaseCommand {
|
|
9
10
|
static description = 'Search skills in the skrr store by keyword (same as `search skills`)';
|
|
10
11
|
static examples = [
|
|
@@ -53,7 +54,7 @@ class SkillsSearch extends base_command_1.BaseCommand {
|
|
|
53
54
|
this.handleApiError(err);
|
|
54
55
|
}
|
|
55
56
|
if (flags.json) {
|
|
56
|
-
this.log(JSON.stringify(response, null, 2));
|
|
57
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
60
|
const r = response;
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../../base-command");
|
|
7
7
|
const store_acquisition_1 = require("../../../lib/store-acquisition");
|
|
8
|
+
const usd_micros_1 = require("../../../lib/usd-micros");
|
|
8
9
|
/**
|
|
9
10
|
* Every purchase or install an agent asked to make for you, newest first
|
|
10
11
|
* (OSK-13403). Before this, a request was only reachable by its id — one from
|
|
@@ -42,7 +43,7 @@ class StoreAcquisitionsList extends base_command_1.BaseCommand {
|
|
|
42
43
|
}
|
|
43
44
|
const requests = result?.requests ?? [];
|
|
44
45
|
if (flags.json) {
|
|
45
|
-
this.printJsonResult((0, list_output_1.listResult)(result, 'requests'));
|
|
46
|
+
this.printJsonResult((0, list_output_1.listResult)((0, usd_micros_1.withUsdPrices)(result), 'requests'));
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
if (requests.length === 0) {
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
const store_acquisition_1 = require("../../../lib/store-acquisition");
|
|
7
|
+
const usd_micros_1 = require("../../../lib/usd-micros");
|
|
7
8
|
/**
|
|
8
9
|
* A purchase an agent asked to make, read from the server's stored request
|
|
9
10
|
* (OSK-12240) — the same data the web approval card shows.
|
|
@@ -38,7 +39,7 @@ class StoreAcquisitionsShow extends base_command_1.BaseCommand {
|
|
|
38
39
|
this.error('The purchase request could not be read.', { exit: 1 });
|
|
39
40
|
}
|
|
40
41
|
if (flags.json) {
|
|
41
|
-
this.log(JSON.stringify(request, null, 2));
|
|
42
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(request), null, 2));
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
for (const line of (0, store_acquisition_1.describeAcquisitionRequestLines)(request)) {
|
|
@@ -4,6 +4,8 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
|
+
const store_listing_1 = require("../../lib/store-listing");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
7
9
|
class StoreBrowse extends base_command_1.BaseCommand {
|
|
8
10
|
static description = 'Browse published agents in the store';
|
|
9
11
|
static examples = [
|
|
@@ -63,7 +65,7 @@ class StoreBrowse extends base_command_1.BaseCommand {
|
|
|
63
65
|
this.handleApiError(err);
|
|
64
66
|
}
|
|
65
67
|
if (flags.json) {
|
|
66
|
-
this.log(JSON.stringify(response, null, 2));
|
|
68
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
67
69
|
return;
|
|
68
70
|
}
|
|
69
71
|
const r = response;
|
|
@@ -77,7 +79,7 @@ class StoreBrowse extends base_command_1.BaseCommand {
|
|
|
77
79
|
name: String(a.name ?? '-'),
|
|
78
80
|
// Price is a property of the LISTING, so it is read from the listing
|
|
79
81
|
// row rather than from anything the agent carries.
|
|
80
|
-
price: a.price ?
|
|
82
|
+
price: (0, store_listing_1.formatListingPrice)(typeof a.price === 'number' ? a.price : null),
|
|
81
83
|
rating: a.rating ? `${Number(a.rating).toFixed(1)} (${a.ratingCount ?? 0})` : '-',
|
|
82
84
|
installs: String(a.installCount ?? 0),
|
|
83
85
|
author: String(a.authorName ?? '-'),
|
|
@@ -12,6 +12,7 @@ export default class StoreInstall extends BaseCommand {
|
|
|
12
12
|
'include-bootstrap': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
'include-memory': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'expected-price': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
'run-on': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
'share-outcomes': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
18
|
};
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const agent_ref_1 = require("../../lib/agent-ref");
|
|
7
7
|
const prompt_1 = require("../../lib/prompt");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
8
9
|
/**
|
|
9
10
|
* One line per placement, said the same way the web install rail says it: the
|
|
10
11
|
* difference is whether a stranger's instructions may reach a connected
|
|
@@ -23,6 +24,7 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
23
24
|
'<%= config.bin %> store install agent_abc123 --run-on local',
|
|
24
25
|
'<%= config.bin %> store install agent_abc123 --share-outcomes',
|
|
25
26
|
'<%= config.bin %> store install agent_abc123 --yes --json',
|
|
27
|
+
'<%= config.bin %> store install agent_abc123 --yes --expected-price 4',
|
|
26
28
|
];
|
|
27
29
|
static args = {
|
|
28
30
|
agent: core_1.Args.string({
|
|
@@ -45,6 +47,10 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
45
47
|
char: 'y',
|
|
46
48
|
description: 'Confirm a paid purchase without prompting. The price and refund terms are still printed.',
|
|
47
49
|
}),
|
|
50
|
+
'expected-price': core_1.Flags.string({
|
|
51
|
+
description: 'Refuse unless the purchase would charge exactly this USD amount (e.g. 4 or 2.50; 0 pins free). ' +
|
|
52
|
+
'Use it to pin the price the person named, not just the one read now.',
|
|
53
|
+
}),
|
|
48
54
|
'run-on': core_1.Flags.string({
|
|
49
55
|
description: 'Where its tools may run. cloud (the default) keeps tools off connected machines; ' +
|
|
50
56
|
'local lets tools use an available connected machine in your account, selected at run time. The agent runs in the cloud either way',
|
|
@@ -121,6 +127,21 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
121
127
|
});
|
|
122
128
|
}
|
|
123
129
|
const charge = Number(quote.charge) || 0;
|
|
130
|
+
// A caller-pinned price binds the purchase to what the PERSON named, not
|
|
131
|
+
// just to what this command read: a listing that moved, or a pin that
|
|
132
|
+
// never matched, refuses here before anything is charged (OSK-18256).
|
|
133
|
+
const expectedMicros = (0, usd_micros_1.expectedPriceFlagMicros)(flags['expected-price']);
|
|
134
|
+
if (expectedMicros === null) {
|
|
135
|
+
this.error(`--expected-price must be a USD amount with at most 2 decimals, e.g. 4 or 2.50 (got "${flags['expected-price']}")`, { exit: 2 });
|
|
136
|
+
}
|
|
137
|
+
if (expectedMicros !== undefined && expectedMicros !== charge) {
|
|
138
|
+
this.failWithCliError({
|
|
139
|
+
message: (0, usd_micros_1.expectedPriceMismatchMessage)(expectedMicros, charge),
|
|
140
|
+
code: 'EXPECTED_PRICE_MISMATCH',
|
|
141
|
+
exit: 1,
|
|
142
|
+
retryable: false,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
124
145
|
if (charge > 0) {
|
|
125
146
|
const name = quote.listingName || agentId;
|
|
126
147
|
const version = quote.versionLabel ? ` v${quote.versionLabel}` : '';
|
|
@@ -134,8 +155,11 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
134
155
|
this.logToStderr(` Buyer terms: ${quote.buyerTerms
|
|
135
156
|
? `${quote.buyerTerms.termsVersion} — ${quote.buyerTerms.artifactUri}`
|
|
136
157
|
: 'not configured'}`);
|
|
158
|
+
// This path records no acceptance — answering yes buys only. Without a
|
|
159
|
+
// prior acceptance the server refuses MARKETPLACE_TERMS_ACCEPTANCE_REQUIRED.
|
|
160
|
+
this.logToStderr(' Buying requires those terms already accepted; a yes here does not accept them.');
|
|
137
161
|
this.logToStderr(` Offer: ${quote.offerVersionId}`);
|
|
138
|
-
const confirmed = await (0, prompt_1.confirmDestructive)(`Buy ${name} for ${(0, data_provider_1.formatStoreAcquisitionPrice)(charge)}
|
|
162
|
+
const confirmed = await (0, prompt_1.confirmDestructive)(`Buy ${name} for ${(0, data_provider_1.formatStoreAcquisitionPrice)(charge)}?`, flags.yes).catch((err) => this.error(err.message, { exit: err.exit ?? 1 }));
|
|
139
163
|
if (!confirmed) {
|
|
140
164
|
this.log('Cancelled. Nothing was bought.');
|
|
141
165
|
return;
|
|
@@ -168,7 +192,7 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
168
192
|
this.handleApiError(err);
|
|
169
193
|
}
|
|
170
194
|
if (flags.json) {
|
|
171
|
-
this.log(JSON.stringify(response, null, 2));
|
|
195
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
172
196
|
return;
|
|
173
197
|
}
|
|
174
198
|
const installedId = response?.installedAgentId;
|
|
@@ -4,6 +4,8 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
|
+
const store_listing_1 = require("../../lib/store-listing");
|
|
8
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
7
9
|
/**
|
|
8
10
|
* What versions of a published agent exist.
|
|
9
11
|
*
|
|
@@ -34,7 +36,7 @@ class StoreReleases extends base_command_1.BaseCommand {
|
|
|
34
36
|
this.handleApiError(err);
|
|
35
37
|
}
|
|
36
38
|
if (flags.json) {
|
|
37
|
-
this.log(JSON.stringify(response, null, 2));
|
|
39
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(response), null, 2));
|
|
38
40
|
return;
|
|
39
41
|
}
|
|
40
42
|
const items = response?.data ?? [];
|
|
@@ -45,7 +47,7 @@ class StoreReleases extends base_command_1.BaseCommand {
|
|
|
45
47
|
(0, format_1.renderTable)(items.map((r) => ({
|
|
46
48
|
id: String(r.id ?? '-'),
|
|
47
49
|
version: String(r.versionLabel ?? '-'),
|
|
48
|
-
price: r.price ?
|
|
50
|
+
price: (0, store_listing_1.formatListingPrice)(typeof r.price === 'number' ? r.price : null),
|
|
49
51
|
published: r.publishedAt ? String(r.publishedAt).slice(0, 10) : '-',
|
|
50
52
|
changelog: String(r.changelog ?? ''),
|
|
51
53
|
})), [
|
|
@@ -6,6 +6,7 @@ const base_command_1 = require("../../base-command");
|
|
|
6
6
|
const agent_ref_1 = require("../../lib/agent-ref");
|
|
7
7
|
const format_1 = require("../../lib/format");
|
|
8
8
|
const store_listing_1 = require("../../lib/store-listing");
|
|
9
|
+
const usd_micros_1 = require("../../lib/usd-micros");
|
|
9
10
|
const web_url_1 = require("../../lib/web-url");
|
|
10
11
|
/** How many releases the detail view lists; `store releases` lists them all. */
|
|
11
12
|
const RECENT_RELEASES = 5;
|
|
@@ -88,7 +89,7 @@ class StoreShow extends base_command_1.BaseCommand {
|
|
|
88
89
|
const listingUrl = (0, web_url_1.webUrl)(this.cliConfig.baseURL, { kind: 'storeListing', agentId });
|
|
89
90
|
const releaseRows = (releases.value?.data ?? []).slice(0, RECENT_RELEASES);
|
|
90
91
|
if (flags.json) {
|
|
91
|
-
this.log(JSON.stringify({
|
|
92
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)({
|
|
92
93
|
agent: listing,
|
|
93
94
|
publisher: {
|
|
94
95
|
handle,
|
|
@@ -102,7 +103,7 @@ class StoreShow extends base_command_1.BaseCommand {
|
|
|
102
103
|
...(releases.error ? { releasesError: releases.error } : {}),
|
|
103
104
|
url: listingUrl,
|
|
104
105
|
installCommand,
|
|
105
|
-
}, null, 2));
|
|
106
|
+
}), null, 2));
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
109
|
const version = listing.versionLabel ? `v${listing.versionLabel}` : 'no version label';
|
|
@@ -42,12 +42,12 @@ class StoreTip extends base_command_1.BaseCommand {
|
|
|
42
42
|
try {
|
|
43
43
|
const result = await data_provider_1.dataService.tipStoreAgent(args.agentId, { amountMicros, tipId });
|
|
44
44
|
if (flags.json) {
|
|
45
|
-
this.log(JSON.stringify(result, null, 2));
|
|
45
|
+
this.log(JSON.stringify((0, usd_micros_1.withUsdPrices)(result), null, 2));
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
this.log(result.replayed
|
|
49
49
|
? `Already tipped under ${tipId}; nothing new was charged.`
|
|
50
|
-
: `Tipped
|
|
50
|
+
: `Tipped ${(0, data_provider_1.formatStoreAcquisitionPrice)(result.amountMicros)} (tip ${tipId}).`);
|
|
51
51
|
}
|
|
52
52
|
catch (err) {
|
|
53
53
|
this.handleApiError(err);
|