@skrr-ai/cli 0.1.118 → 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.
@@ -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;
@@ -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
- let autonomousCredential = (0, credential_resolver_1.resolveTrustedAutonomousCredential)();
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) {
@@ -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 store = await this.resolveStore(flags);
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 store = await this.resolveStore(flags);
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
  }
@@ -5,6 +5,8 @@ export interface ApiFetchOptions {
5
5
  body?: unknown;
6
6
  /** Override credential resolution — useful for tests. */
7
7
  credential?: ResolvedCredential;
8
+ /** Exact admitted-session Memory history GET; never uses owner credentials. */
9
+ sessionRead?: 'memory-history-v1';
8
10
  /**
9
11
  * Extra request headers. Added for `X-Idempotency-Key` (OSK-2806): the
10
12
  * shared data-provider transport takes no per-call options, so a replayed
@@ -37,6 +39,8 @@ export declare class ApiFetchError extends Error {
37
39
  * attributed by guesswork — see `node-adapter.ts`.
38
40
  */
39
41
  readonly requestId?: string;
42
+ /** Client recovery guidance; never changes the server's refusal status/code. */
43
+ recoveryHint?: string;
40
44
  /** Milliseconds the server asked us to wait (`Retry-After`) on a 429. */
41
45
  retryAfterMs?: number;
42
46
  /**
@@ -49,6 +49,7 @@ const workspace_header_1 = require("./workspace-header");
49
49
  const task_runtime_headers_1 = require("./task-runtime-headers");
50
50
  const non_json_response_1 = require("./non-json-response");
51
51
  const rate_limit_retry_1 = require("./rate-limit-retry");
52
+ const memory_history_session_1 = require("./memory-history-session");
52
53
  class ApiFetchError extends Error {
53
54
  status;
54
55
  body;
@@ -65,6 +66,8 @@ class ApiFetchError extends Error {
65
66
  * attributed by guesswork — see `node-adapter.ts`.
66
67
  */
67
68
  requestId;
69
+ /** Client recovery guidance; never changes the server's refusal status/code. */
70
+ recoveryHint;
68
71
  /** Milliseconds the server asked us to wait (`Retry-After`) on a 429. */
69
72
  retryAfterMs;
70
73
  /**
@@ -92,7 +95,11 @@ exports.ApiFetchError = ApiFetchError;
92
95
  * `err.status` / `err.code`.
93
96
  */
94
97
  async function apiFetch(pathOrUrl, opts = {}) {
95
- const sessionCredential = (0, credential_resolver_1.resolveTrustedAutonomousCredential)();
98
+ const historyRead = opts.sessionRead
99
+ ? (0, memory_history_session_1.bindMemoryHistoryRead)(pathOrUrl, opts.method ?? 'GET') : null;
100
+ const sessionCredential = historyRead
101
+ ? { token: historyRead.token, source: 'env-token', kind: (0, credential_resolver_1.kindOf)(historyRead.token) }
102
+ : (0, credential_resolver_1.resolveTrustedAutonomousCredential)();
96
103
  // A few Agent-only APIs (message/voice/telephony intents) deliberately pass
97
104
  // the daemon-issued session token explicitly. Keep those endpoints bound to
98
105
  // the session principal; every other CLI API call in a delegated Agent uses
@@ -104,17 +111,17 @@ async function apiFetch(pathOrUrl, opts = {}) {
104
111
  // equality check against it silently fail open.
105
112
  const envSessionToken = process.env.OVERSKY_SESSION_TOKEN?.trim() || null;
106
113
  const explicitSessionCredential = Boolean(opts.credential?.token && envSessionToken && opts.credential.token === envSessionToken);
107
- const delegatedCli = (0, delegated_cli_1.isDelegatedCliSession)() && !explicitSessionCredential;
114
+ const delegatedCli = (0, delegated_cli_1.isDelegatedCliSession)() && !explicitSessionCredential && !historyRead;
108
115
  const autonomousCredential = delegatedCli
109
116
  ? await (0, delegated_cli_1.fetchDelegatedCliCredential)()
110
117
  : sessionCredential;
111
118
  const baseURL = autonomousCredential ? trustedAutonomousBaseUrl() : (0, config_1.loadConfig)().baseURL;
112
119
  const method = opts.method ?? 'GET';
113
- const url = /^https?:\/\//i.test(pathOrUrl)
120
+ const url = historyRead?.url ?? (/^https?:\/\//i.test(pathOrUrl)
114
121
  ? autonomousCredential
115
122
  ? assertTrustedAutonomousUrl(pathOrUrl, baseURL)
116
123
  : pathOrUrl
117
- : `${baseURL.replace(/\/+$/, '')}${pathOrUrl.startsWith('/') ? '' : '/'}${pathOrUrl}`;
124
+ : `${baseURL.replace(/\/+$/, '')}${pathOrUrl.startsWith('/') ? '' : '/'}${pathOrUrl}`);
118
125
  // A FormData body passes through untouched — fetch sets the multipart
119
126
  // boundary itself, and stringifying would destroy it. Upload commands
120
127
  // (tasks attachments) need this on the session-scoped path, which is not
@@ -190,13 +197,16 @@ async function apiFetch(pathOrUrl, opts = {}) {
190
197
  // OSK-12020 — a fresh proof per attempt for a DPoP-bound hand-off token
191
198
  // (the 401 retry below re-enters here and gets its own). No-op otherwise.
192
199
  Object.assign(headers, await (0, dpop_auth_1.dpopHeadersFor)(credential.token, method, url));
193
- const sent = (0, task_runtime_headers_1.withTaskRuntimeHeaders)((0, workspace_header_1.withWorkspaceHeader)(headers), url, method);
200
+ const sent = (0, task_runtime_headers_1.withTaskRuntimeHeaders)((0, workspace_header_1.withWorkspaceHeader)(headers, historyRead ? {
201
+ OVERSKY_AUTONOMOUS_SESSION: '1',
202
+ OVERSKY_SESSION_WORKSPACE_ID: process.env.OVERSKY_SESSION_WORKSPACE_ID,
203
+ } : process.env), url, method);
194
204
  // E6: a 429 on a GET or an idempotency-keyed write is retried (bounded,
195
205
  // jittered, honouring Retry-After). The last 429's wait is kept for the error.
196
206
  const { response, retryAfterMs } = await (0, rate_limit_retry_1.fetchWithRateLimitRetry)(() => fetch(url, {
197
207
  method,
198
208
  headers: sent,
199
- ...(0, task_runtime_headers_1.taskRuntimeRedirectOptions)(sent),
209
+ ...(historyRead ? { redirect: 'error' } : (0, task_runtime_headers_1.taskRuntimeRedirectOptions)(sent)),
200
210
  body,
201
211
  ...(opts.signal ? { signal: opts.signal } : {}),
202
212
  }), { method, headers: sent, signal: opts.signal });
@@ -218,6 +228,7 @@ async function apiFetch(pathOrUrl, opts = {}) {
218
228
  }
219
229
  }
220
230
  else if (res.status === 401 &&
231
+ !historyRead &&
221
232
  (0, daemonBroker_1.isBrokeredHandoffToken)(cred.token) &&
222
233
  !isAuthEndpoint(pathOrUrl)) {
223
234
  // Broker-mode hand-off credential: nothing was persisted, so there is no
@@ -279,7 +290,14 @@ async function apiFetch(pathOrUrl, opts = {}) {
279
290
  catch {
280
291
  /* ignore body read failures */
281
292
  }
282
- const error = new ApiFetchError(`HTTP ${res.status} ${res.statusText} — ${method} ${pathOrUrl}`, res.status, text, code, method, res.headers.get('x-request-id') || undefined);
293
+ const unsupportedHistory = historyRead && res.status === 404 &&
294
+ (!code || ['API_ROUTE_NOT_FOUND', 'ROUTE_NOT_FOUND'].includes(code));
295
+ const error = new ApiFetchError(unsupportedHistory
296
+ ? 'This server does not support session-scoped Memory history. Upgrade the server before retrying; owner-credential fallback is disabled.'
297
+ : `HTTP ${res.status} ${res.statusText} — ${method} ${pathOrUrl}`, res.status, text, unsupportedHistory ? 'MEMORY_HISTORY_API_UNSUPPORTED' : code, method, res.headers.get('x-request-id') || undefined);
298
+ if (historyRead && res.status === 401) {
299
+ error.recoveryHint = 'Reconnect the managed Agent session and retry. If the refusal persists, check that this server supports session-scoped Memory history. Owner-credential fallback is disabled.';
300
+ }
283
301
  if (brokerFailure)
284
302
  error.brokerFailure = brokerFailure;
285
303
  if (res.status === 429 && lastRetryAfterMs !== undefined)
@@ -0,0 +1,14 @@
1
+ type RuntimeEnv = Record<string, string | undefined>;
2
+ export declare function hasMemoryHistoryRuntime(env?: RuntimeEnv): boolean;
3
+ /** Only this explicit read contract may select a primary session credential. */
4
+ export declare function bindMemoryHistoryRead(pathOrUrl: string, method: string, env?: RuntimeEnv): {
5
+ url: string;
6
+ origin: string;
7
+ token: string;
8
+ };
9
+ export declare function memoryHistorySession(env?: RuntimeEnv): {
10
+ sessionId: string;
11
+ token: string;
12
+ server: URL;
13
+ };
14
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasMemoryHistoryRuntime = hasMemoryHistoryRuntime;
4
+ exports.bindMemoryHistoryRead = bindMemoryHistoryRead;
5
+ exports.memoryHistorySession = memoryHistorySession;
6
+ function hasMemoryHistoryRuntime(env = process.env) {
7
+ // Interactive SDK children can carry the daemon's session tuple without an
8
+ // AutonomousRun or the wrapper's autonomous marker. Partial tuples must not
9
+ // silently turn a managed history read into an owner-account read.
10
+ return env.OVERSKY_AUTONOMOUS_SESSION === '1' ||
11
+ Boolean(env.OVERSKY_SESSION_ID?.trim() || env.OVERSKY_SESSION_TOKEN?.trim());
12
+ }
13
+ function refusal(message, code, status) {
14
+ return Object.assign(new Error(message), { code, status });
15
+ }
16
+ /** Only this explicit read contract may select a primary session credential. */
17
+ function bindMemoryHistoryRead(pathOrUrl, method, env = process.env) {
18
+ const { sessionId, token, server } = memoryHistorySession(env);
19
+ let target;
20
+ try {
21
+ target = new URL(pathOrUrl, server);
22
+ }
23
+ catch {
24
+ throw refusal('Memory history requires the bound session server. Start a new managed Agent session.', 'MEMORY_RUNTIME_ORIGIN_MISMATCH', 403);
25
+ }
26
+ if (target.origin !== server.origin || target.username || target.password) {
27
+ throw refusal('Memory history cannot send its session credential to another server.', 'MEMORY_RUNTIME_ORIGIN_MISMATCH', 403);
28
+ }
29
+ const route = /^\/api\/agentic\/sessions\/([^/]+)\/memory\/agents\/([^/]+)\/versions(?:\/([^/]+))?$/.exec(target.pathname);
30
+ let selectedSession;
31
+ let selectedAgent;
32
+ try {
33
+ selectedSession = route ? decodeURIComponent(route[1]) : undefined;
34
+ selectedAgent = route ? decodeURIComponent(route[2]) : undefined;
35
+ }
36
+ catch { /* malformed encoded selectors are refused below */ }
37
+ if (method.toUpperCase() !== 'GET' || !route || selectedSession !== sessionId ||
38
+ (env.OVERSKY_SESSION_AGENT_ID?.trim() && selectedAgent !== env.OVERSKY_SESSION_AGENT_ID.trim())) {
39
+ throw refusal('Memory history must target this admitted Agent session. Start a session for the selected Agent.', 'MEMORY_RUNTIME_SCOPE_MISMATCH', 403);
40
+ }
41
+ return { url: target.toString(), origin: server.origin, token };
42
+ }
43
+ function memoryHistorySession(env = process.env) {
44
+ const sessionId = env.OVERSKY_SESSION_ID?.trim();
45
+ const token = env.OVERSKY_SESSION_TOKEN?.trim();
46
+ if (!sessionId || !token?.startsWith('agst_')) {
47
+ throw refusal('Memory history requires the bound Agent session credential. Start a managed Agent session; owner credentials cannot replace it.', 'MEMORY_RUNTIME_CREDENTIAL_MISSING', 401);
48
+ }
49
+ let trusted;
50
+ try {
51
+ trusted = new URL(env.OVERSKY_SERVER_URL || '');
52
+ }
53
+ catch {
54
+ throw refusal('Memory history requires the bound session server. Start a new managed Agent session.', 'MEMORY_RUNTIME_ORIGIN_MISMATCH', 403);
55
+ }
56
+ if (!['https:', 'http:'].includes(trusted.protocol) || trusted.username || trusted.password) {
57
+ throw refusal('Memory history cannot send its session credential to another server.', 'MEMORY_RUNTIME_ORIGIN_MISMATCH', 403);
58
+ }
59
+ return { sessionId, token, server: trusted };
60
+ }
@@ -67,6 +67,12 @@ export declare function parseMemoryApiError(error: ApiFetchError): {
67
67
  export declare abstract class ScopedMemoryCommand extends BaseCommand {
68
68
  protected endpoint(agentId: string, suffix?: string): string;
69
69
  protected memoryApi<T>(agentId: string, suffix: string, options?: ApiFetchOptions): Promise<T>;
70
+ protected memoryHistoryApi<T>(flags: ScopedFlags, options: {
71
+ versionId?: string;
72
+ memoryId?: string;
73
+ limit?: number;
74
+ }): Promise<T>;
75
+ private memoryRequest;
70
76
  protected query(flags: ScopedFlags, extra?: Record<string, unknown>): string;
71
77
  protected resolveStore(flags: ScopedFlags, { write }?: {
72
78
  write?: boolean | undefined;
@@ -10,6 +10,7 @@ const core_1 = require("@oclif/core");
10
10
  const node_crypto_1 = require("node:crypto");
11
11
  const base_command_1 = require("../base-command");
12
12
  const api_fetch_1 = require("./api-fetch");
13
+ const memory_history_session_1 = require("./memory-history-session");
13
14
  function parseMemoryStoreResolutions(value) {
14
15
  if (value === undefined)
15
16
  return undefined;
@@ -120,6 +121,9 @@ const ERROR_EXITS = {
120
121
  MEMORY_AUTHORIZATION_STALE: 8,
121
122
  };
122
123
  function parseMemoryApiError(error) {
124
+ if (error.code === 'MEMORY_HISTORY_API_UNSUPPORTED') {
125
+ return { code: error.code, message: error.message, retryable: false };
126
+ }
123
127
  try {
124
128
  const body = JSON.parse(error.body || '{}');
125
129
  const details = {
@@ -136,7 +140,7 @@ function parseMemoryApiError(error) {
136
140
  };
137
141
  return {
138
142
  code: String(body.code || body.error || error.code || 'MEMORY_API_ERROR').toUpperCase(),
139
- message: [body.message || error.message, body.remedy].filter(Boolean).join(' '),
143
+ message: [body.message || error.message, body.remedy, error.recoveryHint].filter(Boolean).join(' '),
140
144
  retryable: body.retryable === true,
141
145
  ...(Object.keys(details).length ? { details } : {}),
142
146
  };
@@ -144,7 +148,7 @@ function parseMemoryApiError(error) {
144
148
  catch {
145
149
  return {
146
150
  code: error.code || 'MEMORY_API_ERROR',
147
- message: error.message,
151
+ message: [error.message, error.recoveryHint].filter(Boolean).join(' '),
148
152
  retryable: false,
149
153
  };
150
154
  }
@@ -154,8 +158,35 @@ class ScopedMemoryCommand extends base_command_1.BaseCommand {
154
158
  return `/api/agents/${encodeURIComponent(agentId)}/memories/workspace${suffix}`;
155
159
  }
156
160
  async memoryApi(agentId, suffix, options = {}) {
161
+ return this.memoryRequest(this.endpoint(agentId, suffix), options);
162
+ }
163
+ async memoryHistoryApi(flags, options) {
164
+ const suffix = options.versionId ? `/${encodeURIComponent(options.versionId)}` : '';
165
+ const query = { memoryId: options.memoryId, limit: options.limit };
166
+ if (!(0, memory_history_session_1.hasMemoryHistoryRuntime)()) {
167
+ const store = await this.resolveStore(flags);
168
+ return this.memoryApi(flags.agent, `/stores/${store.id}/versions${suffix}${this.query(flags, query)}`);
169
+ }
170
+ const { sessionId } = (0, memory_history_session_1.memoryHistorySession)();
171
+ if (Boolean(flags.store) === Boolean(flags.scope)) {
172
+ this.error('Pass exactly one of --store <id> or --scope agent:<id>|space:<id>.', { exit: 2 });
173
+ }
174
+ if (flags.scope && !/^(agent|space):[^:]+$/.test(flags.scope)) {
175
+ this.error('--scope must be agent:<id> or space:<id>.', { exit: 2 });
176
+ }
177
+ if (flags.scope?.startsWith('space:') && !flags.space) {
178
+ this.error(`MEMORY_SPACE_CONTEXT_REQUIRED: --space ${flags.scope.slice(6)} is required when selecting ${flags.scope}.`, { exit: 2, code: 'MEMORY_SPACE_CONTEXT_REQUIRED' });
179
+ }
180
+ // Mount resolution belongs to the admitted session facade. A generic Store
181
+ // preflight would require an owner credential before the session-only read.
182
+ const path = `/api/agentic/sessions/${encodeURIComponent(sessionId)}/memory/agents/${encodeURIComponent(flags.agent)}/versions${suffix}`;
183
+ return this.memoryRequest(`${path}${this.query(flags, {
184
+ ...query, ...(flags.store ? { storeId: flags.store } : { scope: flags.scope }),
185
+ })}`, { sessionRead: 'memory-history-v1' });
186
+ }
187
+ async memoryRequest(path, options) {
157
188
  try {
158
- return await (0, api_fetch_1.apiFetch)(this.endpoint(agentId, suffix), options);
189
+ return await (0, api_fetch_1.apiFetch)(path, options);
159
190
  }
160
191
  catch (error) {
161
192
  if (error instanceof api_fetch_1.ApiFetchError) {
@@ -12,7 +12,7 @@ function withTaskRuntimeHeaders(headers, requestUrl, method, env = process.env)
12
12
  const sent = { ...headers };
13
13
  // A companion credential never travels on a read, another API surface,
14
14
  // or a caller-selected header. Preserve existing nonsecret correlation
15
- // hints outside generic Task mutations for other APIs' provenance checks.
15
+ // hints outside Task authorship mutations for other APIs' provenance checks.
16
16
  for (const key of Object.keys(sent)) {
17
17
  if (key.toLowerCase() === 'x-oversky-session-authorization')
18
18
  delete sent[key];
@@ -31,7 +31,17 @@ function withTaskRuntimeHeaders(headers, requestUrl, method, env = process.env)
31
31
  throw refuseOrigin();
32
32
  return sent;
33
33
  }
34
- if (!/^\/api\/tasks(?:\/|$)/.test(target.pathname))
34
+ // Some platform operations materialize Tasks outside the Task router. Keep
35
+ // their exact POST routes here; action/library edits, picker reads and other
36
+ // integration routes must never receive the companion credential.
37
+ const taskMutation = /^\/api\/tasks(?:\/|$)/.test(target.pathname);
38
+ const taskCreation = method.toUpperCase() === 'POST' && [
39
+ /^\/api\/agents\/[^/]+\/agent-actions\/[^/]+\/run\/?$/,
40
+ /^\/api\/(?:shortcuts|task-templates)\/[^/]+\/(?:instantiate|trigger)\/?$/,
41
+ /^\/api\/templates\/[^/]+\/(?:instantiate|fork)\/?$/,
42
+ /^\/api\/store\/services\/[^/]+\/install\/?$/,
43
+ ].some((route) => route.test(target.pathname));
44
+ if (!taskMutation && !taskCreation)
35
45
  return sent;
36
46
  const names = new Set(['x-oversky-agent-id', 'x-oversky-session-id', 'x-oversky-autonomous-run-id']);
37
47
  for (const key of Object.keys(sent))
@@ -50,7 +60,7 @@ function withTaskRuntimeHeaders(headers, requestUrl, method, env = process.env)
50
60
  throw refuseOrigin();
51
61
  }
52
62
  // The companion credential only travels to the managed runtime's server
53
- // and only to generic Task mutations. Bound routes use it as Authorization.
63
+ // and only to Task mutations/materialization. Bound routes use it as Authorization.
54
64
  if (target.origin !== trusted.origin)
55
65
  throw refuseOrigin();
56
66
  if (!sessionId || !token) {
@@ -73568,6 +73568,8 @@
73568
73568
  "pluginName": "@skrr-ai/cli",
73569
73569
  "pluginType": "core",
73570
73570
  "strict": true,
73571
+ "autonomousCredentialPolicy": "bound-session",
73572
+ "sessionReadPolicy": "memory-history-v1",
73571
73573
  "isESM": false,
73572
73574
  "relativePath": [
73573
73575
  "dist",
@@ -73928,6 +73930,8 @@
73928
73930
  "pluginName": "@skrr-ai/cli",
73929
73931
  "pluginType": "core",
73930
73932
  "strict": true,
73933
+ "autonomousCredentialPolicy": "bound-session",
73934
+ "sessionReadPolicy": "memory-history-v1",
73931
73935
  "isESM": false,
73932
73936
  "relativePath": [
73933
73937
  "dist",
@@ -138173,5 +138177,5 @@
138173
138177
  ]
138174
138178
  }
138175
138179
  },
138176
- "version": "0.1.118"
138180
+ "version": "0.1.119"
138177
138181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrr-ai/cli",
3
- "version": "0.1.118",
3
+ "version": "0.1.119",
4
4
  "description": "Command-line interface for skrr",
5
5
  "license": "ISC",
6
6
  "author": "skrr",