@skrr-ai/cli 0.1.68 → 0.1.70

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.
@@ -374,6 +374,8 @@ class AgentsChat extends base_command_1.BaseCommand {
374
374
  async run() {
375
375
  this.requireAuth();
376
376
  const { args, flags } = await this.parse(AgentsChat);
377
+ if (flags.quick && flags.task)
378
+ this.error('--task requires a runtime session; remove --quick to bind this turn.', { exit: 2 });
377
379
  if (flags.json && !flags['no-stream'] && !flags.quick) {
378
380
  this.error('--json is only supported with --no-stream or --quick; use --jsonl for streaming.', {
379
381
  exit: 2,
@@ -413,6 +415,7 @@ class AgentsChat extends base_command_1.BaseCommand {
413
415
  }
414
416
  }
415
417
  // OSK-2946 — resolve the explicit binding, or warn that there isn't one.
418
+ let boundTaskId;
416
419
  let taskContextBlock = null;
417
420
  if (flags.task) {
418
421
  let task;
@@ -423,6 +426,7 @@ class AgentsChat extends base_command_1.BaseCommand {
423
426
  this.handleApiError(err);
424
427
  }
425
428
  const taskId = String(task.id ?? flags.task);
429
+ boundTaskId = taskId;
426
430
  taskContextBlock = [
427
431
  'You are working on a specific skrr task. This is your canonical scope:',
428
432
  ` task id: ${taskId}`,
@@ -441,8 +445,8 @@ class AgentsChat extends base_command_1.BaseCommand {
441
445
  ` skrr tasks complete ${taskId} --summary "<what you did>" --deliverables "<refs>"`,
442
446
  '',
443
447
  'This is a chat turn, not a managed task run: the task is NOT checked out and its ' +
444
- 'status is not managed for you. Do not go looking for an implicit task context — ' +
445
- 'there is none; use the id above.',
448
+ 'status is not managed for you. The runtime session is bound to this task for ' +
449
+ 'task context and artifact uploads; use the canonical id above.',
446
450
  ].join('\n');
447
451
  if (!flags.jsonl) {
448
452
  this.log(`Bound to task ${task.identifier ?? taskId} (chat turn — task not checked out)`);
@@ -515,6 +519,7 @@ class AgentsChat extends base_command_1.BaseCommand {
515
519
  try {
516
520
  started = await data_provider_1.dataService.startAgenticChat({
517
521
  agentId: args.agentId,
522
+ taskId: boundTaskId,
518
523
  text: contextParts ? `${contextParts}\n\n${prompt}` : prompt,
519
524
  conversationId: threadConversationId,
520
525
  workspaceId: process.env.OVERSKY_WORKSPACE_ID,
@@ -13,8 +13,7 @@ class AgentsReleasesRollback extends base_command_1.BaseCommand {
13
13
  async run() {
14
14
  this.requireAuth();
15
15
  const { args, flags } = await this.parse(AgentsReleasesRollback);
16
- // Through handleApiError so a refusal says why — in particular
17
- // STEP_UP_REQUIRED (OSK-12275), whose remedy is `step-up`, not a retry.
16
+ // Through handleApiError so a release or permission refusal says why.
18
17
  let result;
19
18
  try {
20
19
  result = await data_provider_1.dataService.rollbackAgentRelease({
@@ -36,7 +36,9 @@ function parseReleaseDependencies(entries) {
36
36
  for (const entry of entries) {
37
37
  const match = /^(skill|action):([^@]+)@(store_release_[A-Za-z0-9_-]+)$/.exec(entry);
38
38
  if (!match) {
39
- return { error: `--dependency expects skill:<id>@<store-release-id> or action:<id>@<store-release-id>, got "${entry}".` };
39
+ return {
40
+ error: `--dependency expects skill:<id>@<store-release-id> or action:<id>@<store-release-id>, got "${entry}".`,
41
+ };
40
42
  }
41
43
  dependencies.push({
42
44
  entityType: match[1],
@@ -47,10 +49,9 @@ function parseReleaseDependencies(entries) {
47
49
  return { dependencies };
48
50
  }
49
51
  class AgentsVisibility extends base_command_1.BaseCommand {
50
- static description = 'Set the visibility of an agent (accounts with 2FA need recent step-up for public publishing)';
52
+ static description = 'Set the visibility of an agent';
51
53
  static examples = [
52
54
  '<%= config.bin %> agents visibility <agent-id> --public',
53
- '<%= config.bin %> step-up # required before public publishing when 2FA is enabled',
54
55
  '<%= config.bin %> agents visibility <agent-id> --private',
55
56
  '<%= config.bin %> agents visibility <agent-id> --public --json',
56
57
  '<%= config.bin %> agents visibility <agent-id> --public --capability-rationale "network:*=Looks up flight prices on the web"',
@@ -111,7 +112,9 @@ class AgentsVisibility extends base_command_1.BaseCommand {
111
112
  if (dependencyError)
112
113
  this.error(dependencyError, { exit: 1 });
113
114
  if (dependencies && !isPublic) {
114
- this.error('--dependency declares pins on a public release; pass it with --public.', { exit: 1 });
115
+ this.error('--dependency declares pins on a public release; pass it with --public.', {
116
+ exit: 1,
117
+ });
115
118
  }
116
119
  if (capabilityRationales && !isPublic) {
117
120
  this.error('--capability-rationale applies only when publishing with --public.', {
@@ -125,29 +128,6 @@ class AgentsVisibility extends base_command_1.BaseCommand {
125
128
  exit: 1,
126
129
  });
127
130
  }
128
- // A public release reaches buyers. Accounts with 2FA need a recent
129
- // second-factor proof; accounts without 2FA can publish from a verified
130
- // sign-in session. Read that state before the publish write so the
131
- // remedy is visible in the normal CLI flow instead of only after a 403.
132
- // The server remains authoritative: this is user guidance, not a bypass.
133
- if (isPublic) {
134
- let stepUp;
135
- try {
136
- stepUp = await data_provider_1.dataService.getStepUpStatus(data_provider_1.STORE_PUBLISH_STEP_UP_PURPOSE);
137
- }
138
- catch (err) {
139
- this.handleApiError(err);
140
- }
141
- if (!stepUp.active) {
142
- const bin = this.config.bin;
143
- if (!stepUp.sessionBound) {
144
- this.error(`This credential is not tied to a sign-in session. Run \`${bin} login\` before publishing, then \`${bin} step-up\` if your account has 2FA enabled.`, { code: 'STEP_UP_SESSION_UNBOUND', exit: 2 });
145
- }
146
- if (stepUp.methods.length > 0) {
147
- this.error(`Public publishing needs a recent two-factor verification. Run \`${bin} step-up\`, then retry this command.`, { code: 'STEP_UP_PROOF_REQUIRED', exit: 2 });
148
- }
149
- }
150
- }
151
131
  let result;
152
132
  try {
153
133
  result = await data_provider_1.dataService.setAgentVisibility({
@@ -17,8 +17,9 @@ export default class HarnessesLeasesBilling extends BaseCommand {
17
17
  lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
18
18
  };
19
19
  static flags: {
20
+ 'no-spending-limit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
21
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
- 'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ 'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
23
  };
23
24
  run(): Promise<void>;
24
25
  }
@@ -33,25 +33,30 @@ class HarnessesLeasesBilling extends base_command_1.BaseCommand {
33
33
  lease: core_1.Args.string({ ignoreStdin: true, description: 'Lease ID', required: true }),
34
34
  };
35
35
  static flags = {
36
+ 'no-spending-limit': core_1.Flags.boolean({ description: 'Remove a Dedicated Runtime cap. Other hosted products refuse this.', exclusive: ['spending-limit-cents'] }),
36
37
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
37
38
  'spending-limit-cents': core_1.Flags.integer({
38
39
  description: 'New monthly cap in cents. Refused below what the month has already spent or is projected to. Who pays for a lease is set at create and cannot be changed.',
39
- required: true,
40
+ exclusive: ['no-spending-limit'],
40
41
  min: 1,
41
42
  }),
42
43
  };
43
44
  async run() {
44
45
  this.requireAuth();
45
46
  const { args, flags } = await this.parse(HarnessesLeasesBilling);
47
+ if (flags['spending-limit-cents'] === undefined && !flags['no-spending-limit']) {
48
+ this.error('Choose --spending-limit-cents or --no-spending-limit.', { exit: 2 });
49
+ }
46
50
  try {
47
51
  const response = await (0, harnesses_1.setHarnessLeaseBilling)(args.lease, {
48
- spendingLimitCents: flags['spending-limit-cents'],
52
+ spendingLimitCents: flags['no-spending-limit'] ? null : flags['spending-limit-cents'],
49
53
  });
50
54
  if (flags.json) {
51
55
  this.log(JSON.stringify(response, null, 2));
52
56
  return;
53
57
  }
54
- this.log(`${args.lease} monthly spending cap set to $${(flags['spending-limit-cents'] / 100).toFixed(2)}.`);
58
+ this.log(flags['no-spending-limit'] ? `${args.lease} has no monthly spending cap.` :
59
+ `${args.lease} monthly spending cap set to $${(flags['spending-limit-cents'] / 100).toFixed(2)}.`);
55
60
  }
56
61
  catch (err) {
57
62
  this.handleApiError(err);
@@ -13,6 +13,7 @@ export default class DedicatedMachinesCreate extends DedicatedLeaseCommand {
13
13
  'retention-class': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
14
  'backup-profile': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
15
  'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ 'no-spending-limit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
17
  repository: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
18
  workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
19
  'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -41,13 +41,14 @@ class DedicatedMachinesCreate extends dedicated_lease_command_1.DedicatedLeaseCo
41
41
  'backup-profile': core_1.Flags.string({
42
42
  description: 'crash-consistent (AWS Backup) or application-consistent (guest fsfreeze while the daemon is reachable; scheduled DLM when that plan is enabled). Defaults to the product catalog value.',
43
43
  }),
44
- // Not required, and no client-side value either. Every lease has a cap:
45
- // when create names none, the server applies the product's default cap,
46
- // the "default monthly cap" `machines dedicated catalog` shows. Marking the
47
- // flag required contradicted that catalog line (OSK-8691), and restating
48
- // the default here would be the `--storage-gb` bug above.
49
44
  'spending-limit-cents': core_1.Flags.integer({
50
- description: "Monthly spending cap in cents. Omit it to take the product's default cap (see `machines dedicated catalog`); change it later with `machines dedicated spending-limit`.",
45
+ description: 'Optional monthly spending cap in cents. New machines default to no cap; restore inherits the source cap.',
46
+ min: 1,
47
+ exclusive: ['no-spending-limit'],
48
+ }),
49
+ 'no-spending-limit': core_1.Flags.boolean({
50
+ description: 'Run without a monthly spending cap. Compute and retained storage still bill.',
51
+ exclusive: ['spending-limit-cents'],
51
52
  }),
52
53
  repository: core_1.Flags.string({
53
54
  description: 'Default GitHub repository (owner/repo) for git credentials on the machine. Requires the GitHub App installed for it; a clone of another repository the App covers still works.',
@@ -81,7 +82,7 @@ class DedicatedMachinesCreate extends dedicated_lease_command_1.DedicatedLeaseCo
81
82
  requestId,
82
83
  displayName: flags.name,
83
84
  sizePreset,
84
- monthlySpendingLimitCents: flags['spending-limit-cents'],
85
+ monthlySpendingLimitCents: flags['no-spending-limit'] ? null : flags['spending-limit-cents'],
85
86
  regionClass: flags['region-class'],
86
87
  storageGb: flags['storage-gb'],
87
88
  retentionClass: flags['retention-class'],
@@ -100,7 +101,7 @@ class DedicatedMachinesCreate extends dedicated_lease_command_1.DedicatedLeaseCo
100
101
  sizePreset,
101
102
  storageGb: flags['storage-gb'],
102
103
  retentionClass: flags['retention-class'],
103
- spendingLimitCents: flags['spending-limit-cents'],
104
+ spendingLimitCents: flags['no-spending-limit'] ? null : flags['spending-limit-cents'],
104
105
  });
105
106
  if (flags['dry-run']) {
106
107
  if (flags.json) {
@@ -25,6 +25,7 @@ export default class DedicatedMachinesRestore extends DedicatedLeaseCommand {
25
25
  interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
26
26
  name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
27
27
  'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
28
+ 'no-spending-limit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
28
29
  'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
29
30
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
30
31
  };
@@ -36,8 +36,13 @@ class DedicatedMachinesRestore extends dedicated_lease_command_1.DedicatedLeaseC
36
36
  description: 'Display name for the new machine (defaults to the deleted one, "(restored)")',
37
37
  }),
38
38
  'spending-limit-cents': core_1.Flags.integer({
39
- description: "Monthly spending cap for the new machine (defaults to the deleted machine's)",
39
+ description: 'Optional monthly spending cap in cents. New machines default to no cap; restore inherits the source cap.',
40
40
  min: 1,
41
+ exclusive: ['no-spending-limit'],
42
+ }),
43
+ 'no-spending-limit': core_1.Flags.boolean({
44
+ description: 'Run without a monthly spending cap. Compute and retained storage still bill.',
45
+ exclusive: ['spending-limit-cents'],
41
46
  }),
42
47
  'request-id': core_1.Flags.string({
43
48
  description: 'Idempotency key. Reuse it to safely retry the same restore.',
@@ -53,6 +58,7 @@ class DedicatedMachinesRestore extends dedicated_lease_command_1.DedicatedLeaseC
53
58
  ...this.scopeFrom(flags),
54
59
  requestId,
55
60
  ...(flags.name ? { displayName: flags.name } : {}),
61
+ ...(flags['no-spending-limit'] ? { monthlySpendingLimitCents: null } : {}),
56
62
  ...(flags['spending-limit-cents'] !== undefined
57
63
  ? { monthlySpendingLimitCents: flags['spending-limit-cents'] }
58
64
  : {}),
@@ -2,7 +2,7 @@ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
2
  /**
3
3
  * `skrr machines dedicated spending-limit` — change the monthly cap after create.
4
4
  *
5
- * The cap is the ONE guardrail on a machine with no wall-clock TTL: when a
5
+ * An optional cap is a spending guardrail on a machine with no wall-clock TTL: when a
6
6
  * month's spend reaches it, the platform stops compute and keeps the workspace.
7
7
  * It could be set at create and changed from the web lease card, but not from
8
8
  * here — so an operator who hit it at 2am had to find a browser to raise it,
@@ -15,7 +15,8 @@ export default class DedicatedMachinesSpendingLimit extends DedicatedLeaseComman
15
15
  lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
16
16
  };
17
17
  static flags: {
18
- cents: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ cents: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ 'no-spending-limit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
20
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
21
  };
21
22
  run(): Promise<void>;
@@ -6,7 +6,7 @@ const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
6
  /**
7
7
  * `skrr machines dedicated spending-limit` — change the monthly cap after create.
8
8
  *
9
- * The cap is the ONE guardrail on a machine with no wall-clock TTL: when a
9
+ * An optional cap is a spending guardrail on a machine with no wall-clock TTL: when a
10
10
  * month's spend reaches it, the platform stops compute and keeps the workspace.
11
11
  * It could be set at create and changed from the web lease card, but not from
12
12
  * here — so an operator who hit it at 2am had to find a browser to raise it,
@@ -28,16 +28,20 @@ class DedicatedMachinesSpendingLimit extends dedicated_lease_command_1.Dedicated
28
28
  static flags = {
29
29
  cents: core_1.Flags.integer({
30
30
  description: 'New monthly cap in cents (30000 = $300). Refused below what this month has already spent or is projected to.',
31
- required: true,
31
+ exclusive: ['no-spending-limit'],
32
32
  min: 1,
33
33
  }),
34
+ 'no-spending-limit': core_1.Flags.boolean({ description: 'Remove the cap. Compute and storage still bill.', exclusive: ['cents'] }),
34
35
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
35
36
  };
36
37
  async run() {
37
38
  this.requireAuth();
38
39
  const { args, flags } = await this.parse(DedicatedMachinesSpendingLimit);
40
+ if (flags.cents === undefined && !flags['no-spending-limit']) {
41
+ this.error('Choose --cents or --no-spending-limit.', { exit: 2 });
42
+ }
39
43
  const leaseId = await this.resolveLeaseArg(args.lease);
40
- const response = await this.callDedicated(() => (0, dedicated_machines_1.setDedicatedRuntimeSpendingLimit)(leaseId, flags.cents, this.scopeFrom(flags)));
44
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.setDedicatedRuntimeSpendingLimit)(leaseId, flags['no-spending-limit'] ? null : flags.cents, this.scopeFrom(flags)));
41
45
  if (flags.json) {
42
46
  this.log(JSON.stringify(response, null, 2));
43
47
  return;
@@ -1,11 +1,10 @@
1
1
  import { BaseCommand } from '../base-command';
2
2
  /**
3
- * `skrr step-up` — confirm it is you before publishing to the Store
3
+ * `skrr step-up` — confirm it is you for a gated Store administration action
4
4
  * (OSK-12275).
5
5
  *
6
- * Making a release public, rolling the public listing back, or publishing a
7
- * governed release all reach buyers, so the server refuses them from a login
8
- * that has not recently proved a second factor. This command proves one — the
6
+ * Governed release administration may ask for a recent second factor.
7
+ * Self-service Agent publishing and rollback do not. This command proves one — the
9
8
  * code from the account's authenticator app, or an unused backup code — and
10
9
  * the verification is bound to THIS login only, for a few minutes. A token
11
10
  * stolen from another device, or a browser session, is not covered by it.
@@ -6,18 +6,17 @@ const base_command_1 = require("../base-command");
6
6
  const prompt_1 = require("../lib/prompt");
7
7
  const step_up_1 = require("../lib/step-up");
8
8
  /**
9
- * `skrr step-up` — confirm it is you before publishing to the Store
9
+ * `skrr step-up` — confirm it is you for a gated Store administration action
10
10
  * (OSK-12275).
11
11
  *
12
- * Making a release public, rolling the public listing back, or publishing a
13
- * governed release all reach buyers, so the server refuses them from a login
14
- * that has not recently proved a second factor. This command proves one — the
12
+ * Governed release administration may ask for a recent second factor.
13
+ * Self-service Agent publishing and rollback do not. This command proves one — the
15
14
  * code from the account's authenticator app, or an unused backup code — and
16
15
  * the verification is bound to THIS login only, for a few minutes. A token
17
16
  * stolen from another device, or a browser session, is not covered by it.
18
17
  */
19
18
  class StepUp extends base_command_1.BaseCommand {
20
- static description = 'Confirm it is you with an authenticator code before publishing to the Store';
19
+ static description = 'Confirm it is you with an authenticator code for gated Store administration';
21
20
  static examples = [
22
21
  '<%= config.bin %> step-up',
23
22
  '<%= config.bin %> step-up --otp 123456',
@@ -34,7 +33,7 @@ class StepUp extends base_command_1.BaseCommand {
34
33
  exclusive: ['otp', 'status'],
35
34
  }),
36
35
  status: core_1.Flags.boolean({
37
- description: 'Show whether this login is verified for publishing, without verifying',
36
+ description: 'Show whether this login has a recent second-factor proof',
38
37
  }),
39
38
  json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
40
39
  };
@@ -56,15 +55,15 @@ class StepUp extends base_command_1.BaseCommand {
56
55
  return;
57
56
  }
58
57
  this.log(status.active
59
- ? `Verified for publishing from this login until ${(0, step_up_1.formatStepUpExpiry)(status.expiresAt)}.`
60
- : `Not verified for publishing from this login. Run \`${bin} step-up\` to verify.`);
58
+ ? `Verified for gated Store actions from this login until ${(0, step_up_1.formatStepUpExpiry)(status.expiresAt)}.`
59
+ : `No recent second-factor proof for this login. Run \`${bin} step-up\` to verify.`);
61
60
  return;
62
61
  }
63
62
  if (!status.sessionBound) {
64
- this.error(`This credential is not tied to a sign-in session, so it cannot be verified for publishing. Run \`${bin} login\`, then \`${bin} step-up\`.`, { code: 'STEP_UP_SESSION_UNBOUND', exit: 2 });
63
+ this.error(`This credential is not tied to a sign-in session, so it cannot record a second-factor proof. Run \`${bin} login\`, then \`${bin} step-up\`.`, { code: 'STEP_UP_SESSION_UNBOUND', exit: 2 });
65
64
  }
66
65
  if (status.methods.length === 0) {
67
- this.error('Publishing to the Store needs two-factor authentication, and this account has none. ' +
66
+ this.error('A second-factor proof needs two-factor authentication, and this account has none. ' +
68
67
  `Turn it on in the web app (Settings → Account → Two-factor authentication), then run \`${bin} step-up\`.`, { code: 'STEP_UP_TWO_FACTOR_REQUIRED', exit: 2 });
69
68
  }
70
69
  let token = flags.otp?.trim();
@@ -90,7 +89,7 @@ class StepUp extends base_command_1.BaseCommand {
90
89
  return;
91
90
  }
92
91
  const via = result.method === 'backup_code' ? 'a backup code' : 'your authenticator app';
93
- this.log(`Verified with ${via}. Store publishing from this login is allowed until ${(0, step_up_1.formatStepUpExpiry)(result.expiresAt)}.`);
92
+ this.log(`Verified with ${via}. Gated Store actions from this login are allowed until ${(0, step_up_1.formatStepUpExpiry)(result.expiresAt)}.`);
94
93
  }
95
94
  }
96
95
  exports.default = StepUp;
@@ -244,7 +244,7 @@ export interface CreateDedicatedRuntimeInput extends DedicatedRuntimeScope {
244
244
  storageGb?: number;
245
245
  retentionClass?: string;
246
246
  backupProfile?: 'crash-consistent' | 'application-consistent';
247
- monthlySpendingLimitCents?: number;
247
+ monthlySpendingLimitCents?: number | null;
248
248
  repositoryRef?: string;
249
249
  }
250
250
  export interface DedicatedRuntimeResponse {
@@ -267,7 +267,7 @@ export declare function dedicatedRuntimeCreateInput(input: {
267
267
  requestId: string;
268
268
  displayName: string;
269
269
  sizePreset: string;
270
- monthlySpendingLimitCents?: number;
270
+ monthlySpendingLimitCents?: number | null;
271
271
  regionClass?: string;
272
272
  storageGb?: number;
273
273
  retentionClass?: string;
@@ -345,7 +345,7 @@ export declare function growDedicatedRuntime(leaseId: string, storageGb: number,
345
345
  */
346
346
  export declare function restoreDeletedDedicatedRuntime(leaseId: string, options?: {
347
347
  displayName?: string;
348
- monthlySpendingLimitCents?: number;
348
+ monthlySpendingLimitCents?: number | null;
349
349
  requestId?: string;
350
350
  } & DedicatedRuntimeScope): Promise<DedicatedRuntimeResponse>;
351
351
  /**
@@ -356,7 +356,7 @@ export declare function restoreDeletedDedicatedRuntime(leaseId: string, options?
356
356
  * already spent (or is projected to) is refused rather than stopping the machine
357
357
  * on the next reconciler pass.
358
358
  */
359
- export declare function setDedicatedRuntimeSpendingLimit(leaseId: string, spendingLimitCents: number, scope?: DedicatedRuntimeScope): Promise<DedicatedRuntimeResponse>;
359
+ export declare function setDedicatedRuntimeSpendingLimit(leaseId: string, spendingLimitCents: number | null, scope?: DedicatedRuntimeScope): Promise<DedicatedRuntimeResponse>;
360
360
  export declare function closeDedicatedRuntimeIncidentHold(leaseId: string, options?: {
361
361
  requestId?: string;
362
362
  } & DedicatedRuntimeScope): Promise<DedicatedRuntimeResponse>;
@@ -687,7 +687,7 @@ export interface DedicatedCreateChoices {
687
687
  sizePreset: string;
688
688
  storageGb?: number;
689
689
  retentionClass?: string;
690
- spendingLimitCents?: number;
690
+ spendingLimitCents?: number | null;
691
691
  }
692
692
  /**
693
693
  * What a create is about to buy, in the words and numbers the catalog uses.
@@ -569,15 +569,16 @@ function dedicatedSpendSummary(lease) {
569
569
  const billing = lease.billing;
570
570
  if (!billing)
571
571
  return '-';
572
- const cap = billing.monthlySpendLimitCents ?? billing.spendingLimitCents;
572
+ const cap = billing.monthlySpendLimitCents !== undefined
573
+ ? billing.monthlySpendLimitCents : billing.spendingLimitCents;
573
574
  if (billing.spendStatusUnavailable) {
574
- return `spend unavailable right now · cap ${formatUsdCents(cap)}`;
575
+ return `spend unavailable right now · ${cap === null ? 'no monthly cap' : `cap ${formatUsdCents(cap)}`}`;
575
576
  }
576
577
  const spent = billing.currentMonthSpendCents;
577
578
  const projected = billing.projectedCurrentMonthSpendCents;
578
579
  const parts = [
579
580
  `${formatUsdCents(spent)} this month for machines of this type`,
580
- `${formatUsdCents(cap)} cap for this machine`,
581
+ cap === null ? 'no monthly cap' : `${formatUsdCents(cap)} cap for this machine`,
581
582
  ];
582
583
  if (typeof projected === 'number' && projected !== spent) {
583
584
  parts.push(`projected ${formatUsdCents(projected)}`);
@@ -1117,10 +1118,11 @@ function dedicatedCreateSummary(catalog, choices) {
1117
1118
  ? `${retentionClass}${choices.retentionClass === undefined ? ' (catalog default)' : ''}`
1118
1119
  : 'server default';
1119
1120
  const retains = retentionClass !== undefined && retentionClass !== 'none';
1120
- const capCents = choices.spendingLimitCents ?? catalog?.defaultMonthlySpendingLimitCents;
1121
+ const capCents = choices.spendingLimitCents !== undefined
1122
+ ? choices.spendingLimitCents : catalog?.defaultMonthlySpendingLimitCents;
1121
1123
  const cap = capCents !== undefined && capCents !== null
1122
1124
  ? `${formatUsdCents(capCents)} per month${choices.spendingLimitCents === undefined ? ' (catalog default)' : ''}`
1123
- : 'server default';
1125
+ : capCents === null ? 'no cap — compute and retained storage still bill' : 'server default';
1124
1126
  return [
1125
1127
  `Create Dedicated Runtime "${choices.name}" — it bills while it runs:`,
1126
1128
  ` size ${choices.sizePreset} — ${spec}`,
@@ -416,6 +416,8 @@ function socketOptions(token) {
416
416
  path: '/ws/agentic',
417
417
  auth: {
418
418
  token,
419
+ // This proves origin only; the normal CLI token retains full execution authority.
420
+ ...(process.env.OVERSKY_SESSION_TOKEN ? { executionOriginToken: process.env.OVERSKY_SESSION_TOKEN } : {}),
419
421
  ...(0, data_provider_1.getClientIdentityAuth)(),
420
422
  clientPlatform: 'cli',
421
423
  clientOs: process.platform === 'darwin' ? 'macos' : process.platform,
@@ -63,6 +63,10 @@ const MIME_TYPES = {
63
63
  '.jpg': 'image/jpeg',
64
64
  '.js': 'text/javascript',
65
65
  '.json': 'application/json',
66
+ // A stream of JSON values is text evidence, not one JSON document.
67
+ // Preserve the original bytes and filename rather than forcing an array.
68
+ '.jsonl': 'text/plain',
69
+ '.ndjson': 'text/plain',
66
70
  '.log': 'text/plain',
67
71
  '.m4a': 'audio/m4a',
68
72
  '.m4v': 'video/m4v',
@@ -134,6 +134,11 @@ export interface HarnessLease {
134
134
  billing?: {
135
135
  billableState?: string;
136
136
  monthlySpendLimitCents?: number | null;
137
+ /** Monthly total shared by all machines of this product in the billing account. */
138
+ spendScope?: {
139
+ kind: 'owner_product' | 'workspace_product';
140
+ machineProduct: string;
141
+ };
137
142
  currentMonthSpendCents?: number;
138
143
  openUsageEstimateCents?: number;
139
144
  projectedCurrentMonthSpendCents?: number;
@@ -1,14 +1,12 @@
1
1
  /**
2
- * What the CLI says about step-up authentication before Store publishing
2
+ * What the CLI says about step-up authentication for gated Store actions
3
3
  * (OSK-12275).
4
4
  *
5
- * A public release reaches everyone who installs it, so the server refuses to
6
- * publish one, or to move the release buyers are served, on the strength of a
7
- * CLI token alone: it answers `STEP_UP_REQUIRED` until this same login has
8
- * proved a second factor through `skrr step-up`. The vocabulary (the code, the
5
+ * An explicitly gated Store action answers `STEP_UP_REQUIRED` until this login
6
+ * has proved a second factor through `skrr step-up`. The vocabulary (the code, the
9
7
  * reasons, the window) is `@skrr-ai/data-provider`'s; only the sentences live
10
8
  * here, because each reason has a different next step and a refusal that says
11
- * "forbidden" would leave a publisher guessing which one applies.
9
+ * "forbidden" would leave the caller guessing which one applies.
12
10
  */
13
11
  import type { TStepUpChallenge } from '@skrr-ai/data-provider';
14
12
  /**
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.describeStepUpRequired = describeStepUpRequired;
4
4
  exports.formatStepUpExpiry = formatStepUpExpiry;
5
- const NOTHING_CHANGED = 'Nothing was published or changed.';
5
+ const NOTHING_CHANGED = 'Nothing changed.';
6
6
  function windowPhrase(windowSeconds) {
7
7
  const minutes = Math.max(1, Math.round((windowSeconds ?? 600) / 60));
8
8
  return `${minutes} minute${minutes === 1 ? '' : 's'}`;
@@ -17,18 +17,18 @@ function describeStepUpRequired(challenge, bin) {
17
17
  switch (challenge?.reason) {
18
18
  case 'two_factor_not_enabled':
19
19
  return [
20
- `Publishing to the Store needs two-factor authentication, and this account has none. ${NOTHING_CHANGED}`,
20
+ `This action needs two-factor authentication, and this account has none. ${NOTHING_CHANGED}`,
21
21
  'Turn it on in the web app (Settings → Account → Two-factor authentication),',
22
22
  `then run \`${bin} step-up\` and run this command again within ${window}.`,
23
23
  ].join('\n');
24
24
  case 'credential_not_session_bound':
25
25
  return [
26
- `This credential is not tied to a sign-in session, so it cannot be verified for publishing. ${NOTHING_CHANGED}`,
26
+ `This credential is not tied to a sign-in session, so it cannot record a second-factor proof. ${NOTHING_CHANGED}`,
27
27
  `Run \`${bin} login\`, then \`${bin} step-up\`, and run this command again within ${window}.`,
28
28
  ].join('\n');
29
29
  default:
30
30
  return [
31
- `Publishing needs a fresh identity check: a public release reaches everyone who installs it, so this login alone is not enough. ${NOTHING_CHANGED}`,
31
+ `This action needs a fresh identity check; this login alone is not enough. ${NOTHING_CHANGED}`,
32
32
  `Run \`${bin} step-up\` and enter the code from your authenticator app, then run this command again within ${window}.`,
33
33
  ].join('\n');
34
34
  }