@permute/sdk 0.7.0 → 0.8.1

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.
@@ -0,0 +1,106 @@
1
+ import { z } from 'zod';
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
6
+ import { setTimeout } from 'node:timers/promises';
7
+ export const TOKEN_REFRESH_BUFFER_MS = 60_000;
8
+ const LoginCredentialsSchema = z.object({
9
+ issuer: z.string().url(),
10
+ apiUrl: z.string().url(),
11
+ workspaceId: z.string().min(1).optional(),
12
+ organizationId: z.string().min(1).optional(),
13
+ sessionId: z.string().min(1),
14
+ access: z.string().min(1),
15
+ refresh: z.string().min(1),
16
+ expiresAt: z.number().finite(),
17
+ });
18
+ /** Credentials are cached in memory only; disk holds a lock and a non-secret change marker. */
19
+ export class SystemCredentialStore {
20
+ issuer;
21
+ onAccess;
22
+ account;
23
+ directory = join(homedir(), '.config', 'permute', 'auth');
24
+ revisionPath;
25
+ cached;
26
+ announced = false;
27
+ constructor(issuer, onAccess) {
28
+ this.issuer = issuer;
29
+ this.onAccess = onAccess;
30
+ this.account = createHash('sha256').update(issuer).digest('hex');
31
+ this.revisionPath = join(this.directory, `${this.account}.revision`);
32
+ }
33
+ async entry() {
34
+ const { AsyncEntry } = await import('@napi-rs/keyring');
35
+ if (!this.announced) {
36
+ this.onAccess?.(this.issuer);
37
+ this.announced = true;
38
+ }
39
+ return new AsyncEntry('permute-cli', this.account, { linux: { store: 'secret-service' } });
40
+ }
41
+ async read() {
42
+ const revision = await readFile(this.revisionPath, 'utf8').catch((error) => {
43
+ if (error.code === 'ENOENT')
44
+ return null;
45
+ throw error;
46
+ });
47
+ if (this.cached?.revision === revision && this.cached.value.expiresAt > Date.now() + TOKEN_REFRESH_BUFFER_MS)
48
+ return { ...this.cached.value };
49
+ this.cached = undefined;
50
+ const value = await (await this.entry()).getPassword();
51
+ if (!value)
52
+ return null;
53
+ const credentials = this.validate(JSON.parse(value));
54
+ this.cached = { revision, value: credentials };
55
+ return { ...credentials };
56
+ }
57
+ validate(value) {
58
+ const parsed = LoginCredentialsSchema.safeParse(value);
59
+ if (!parsed.success || parsed.data.issuer !== this.issuer)
60
+ throw new Error('Stored login is invalid. Run permute auth login again.');
61
+ return parsed.data;
62
+ }
63
+ async write(value) {
64
+ const credentials = this.validate(value);
65
+ this.cached = undefined;
66
+ await (await this.entry()).setPassword(JSON.stringify(credentials));
67
+ const revision = await this.markChanged();
68
+ this.cached = { revision, value: credentials };
69
+ }
70
+ async remove() {
71
+ this.cached = undefined;
72
+ const entry = await this.entry();
73
+ if (await entry.getPassword())
74
+ await entry.deletePassword();
75
+ await this.markChanged();
76
+ }
77
+ async markChanged() {
78
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
79
+ const revision = randomUUID();
80
+ await writeFile(this.revisionPath, revision, { mode: 0o600 });
81
+ return revision;
82
+ }
83
+ async exclusive(run) {
84
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
85
+ const lock = join(this.directory, `${this.account}.lock`);
86
+ const deadline = Date.now() + 30_000;
87
+ while (true) {
88
+ const acquired = await mkdir(lock, { mode: 0o700 }).then(() => true, (error) => {
89
+ if (error.code !== 'EEXIST')
90
+ throw error;
91
+ return false;
92
+ });
93
+ if (acquired)
94
+ break;
95
+ if (Date.now() >= deadline)
96
+ throw new Error(`Another process is updating this login. Retry after it finishes. If a process crashed, stop other Permute CLI processes before removing ${lock}.`);
97
+ await setTimeout(100);
98
+ }
99
+ try {
100
+ return await run();
101
+ }
102
+ finally {
103
+ await rm(lock, { recursive: true, force: true });
104
+ }
105
+ }
106
+ }
package/dist/auth.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './auth/oauth.js';
package/dist/auth.js ADDED
@@ -0,0 +1 @@
1
+ export * from './auth/oauth.js';
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function runCli(args?: string[]): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from 'node:http';
3
+ import { spawn } from 'node:child_process';
4
+ import { parseArgs } from 'node:util';
5
+ import { pathToFileURL } from 'node:url';
6
+ import { realpathSync } from 'node:fs';
7
+ import { OAuthLogin } from './auth.js';
8
+ function openBrowser(url) {
9
+ const command = process.platform === 'darwin' ? 'open' : process.platform === 'linux' ? 'xdg-open' : undefined;
10
+ if (!command)
11
+ return;
12
+ const child = spawn(command, [url], { stdio: 'ignore' });
13
+ child.on('error', () => {
14
+ /* The printed link also works when no local browser is available. */
15
+ });
16
+ child.unref();
17
+ }
18
+ async function browserLogin(login, open) {
19
+ let destination;
20
+ let resolveCallback;
21
+ let rejectCallback;
22
+ const callback = new Promise((resolve, reject) => {
23
+ resolveCallback = resolve;
24
+ rejectCallback = reject;
25
+ });
26
+ const server = createServer((request, response) => {
27
+ if (!destination ||
28
+ request.method !== 'GET' ||
29
+ request.headers.host !== new URL(destination.redirectURI).host ||
30
+ !request.url?.startsWith('/callback?')) {
31
+ response.writeHead(400).end('This callback does not match the login request.');
32
+ return;
33
+ }
34
+ const url = new URL(request.url, destination.redirectURI);
35
+ if (url.searchParams.get('state') !== destination.state) {
36
+ response.writeHead(400).end('This callback does not match the login request.');
37
+ return;
38
+ }
39
+ response
40
+ .writeHead(200, {
41
+ 'Content-Type': 'text/plain',
42
+ 'Cache-Control': 'no-store',
43
+ 'Content-Security-Policy': "default-src 'none'",
44
+ })
45
+ .end('Return to your terminal to finish connecting. You can close this tab.');
46
+ resolveCallback(url);
47
+ });
48
+ await new Promise((resolve, reject) => {
49
+ server.once('error', reject);
50
+ server.listen(0, '127.0.0.1', resolve);
51
+ });
52
+ const address = server.address();
53
+ if (!address || typeof address === 'string')
54
+ throw new Error('Could not open a loopback callback');
55
+ destination = login.beginBrowser(`http://127.0.0.1:${address.port}/callback`);
56
+ const timeout = setTimeout(() => rejectCallback(new Error('Login timed out. Start login again.')), 600_000);
57
+ const cancel = () => rejectCallback(new Error('Login canceled.'));
58
+ process.once('SIGINT', cancel);
59
+ try {
60
+ console.log(`Open this link to connect Permute CLI:\n${destination.url}`);
61
+ if (open)
62
+ openBrowser(destination.url);
63
+ return await login.finishBrowser(destination, await callback);
64
+ }
65
+ finally {
66
+ clearTimeout(timeout);
67
+ process.off('SIGINT', cancel);
68
+ server.closeAllConnections();
69
+ server.close();
70
+ }
71
+ }
72
+ export async function runCli(args = process.argv.slice(2)) {
73
+ const { values, positionals } = parseArgs({
74
+ args,
75
+ allowPositionals: true,
76
+ options: {
77
+ issuer: { type: 'string' },
78
+ 'api-url': { type: 'string' },
79
+ 'device-code': { type: 'boolean' },
80
+ 'no-browser': { type: 'boolean' },
81
+ help: { type: 'boolean' },
82
+ },
83
+ });
84
+ const [area, command] = positionals;
85
+ if (values.help || area !== 'auth' || !['login', 'logout', 'status'].includes(command ?? '')) {
86
+ console.log('permute auth login [--device-code] [--no-browser]\npermute auth status\npermute auth logout\n\nUse --issuer and --api-url together for a development environment.');
87
+ if (!values.help)
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+ if (!!values.issuer !== !!values['api-url'])
92
+ throw new Error('Provide both --issuer and --api-url for another environment.');
93
+ const login = new OAuthLogin({
94
+ issuer: values.issuer,
95
+ apiUrl: values['api-url'],
96
+ onCredentialStoreAccess: (issuer) => {
97
+ const store = process.platform === 'darwin' ? 'macOS Keychain' : 'your OS credential store';
98
+ console.error(`Permute CLI is accessing ${store} for ${issuer} (entry: permute-cli).`);
99
+ },
100
+ });
101
+ if (command === 'logout') {
102
+ await login.logout();
103
+ console.log('CLI login revoked and removed from this device.');
104
+ return;
105
+ }
106
+ if (command === 'status') {
107
+ const credentials = await login.credentials();
108
+ console.log(`Connected to ${credentials.apiUrl}\nOrganization: ${credentials.organizationId ?? 'Not specified'}\nWorkspace: ${credentials.workspaceId ?? 'All accessible workspaces in this organization'}`);
109
+ return;
110
+ }
111
+ const controller = new AbortController();
112
+ const cancel = () => controller.abort();
113
+ process.once('SIGINT', cancel);
114
+ try {
115
+ if (values['device-code']) {
116
+ const request = await login.beginDevice();
117
+ console.log(`Open this link on any device:\n${request.url}\n\nConfirm this code: ${request.userCode}\nWaiting for your approval…`);
118
+ if (!values['no-browser'])
119
+ openBrowser(request.url);
120
+ await login.finishDevice(request, controller.signal);
121
+ }
122
+ else
123
+ await browserLogin(login, !values['no-browser']);
124
+ console.log('Connected. Credentials are saved in your operating system’s credential store.');
125
+ }
126
+ finally {
127
+ process.off('SIGINT', cancel);
128
+ }
129
+ }
130
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href)
131
+ runCli().catch(() => {
132
+ console.error('Could not complete authentication. Ensure your OS credential store is available, then retry. Use --device-code --no-browser to approve from another device.');
133
+ process.exitCode = 1;
134
+ });
package/dist/client.d.ts CHANGED
@@ -1,6 +1,7 @@
1
+ import type { EmailSender, EmailSendRequest, EmailReceipt, PermissionGrant, PermissionGrantInput, PermissionGrantUpdate, PermissionGrantQuery, PermissionGrantList, PermissionGrantRevoked, PermissionInspectionInput, PermissionInspection, AccessRequest, AccessRequestInput, AccessRequestQuery, AccessRequestList, AccessRequestDecision } from './types.js';
1
2
  export { PermuteApiError } from './errors.js';
2
- import type { BusinessAction, BusinessActionList, ActionCreateRequest, ActionDefinition, ActionDefinitionSaveRequest, ActionDefinitionSaved, ActionRequest, ActionReceipt } from './types.js';
3
- import type { ConnectorSession, ConnectorSessionCreated, ConnectorSessionCreateRequest, Database, AppDraft, AppAccess, AppAddressSettings, AppAddressSetRequest, AppAccessSetRequest, AppDraftList, AppCreateRequest, AppUpdateRequest, AppDeleted, AppUploadsRequest, AppUploads, AppSiteSaveRequest, AppSourceFileQuery, AppSourceFileContent, AppGrants, AppGrantSetRequest, AppUploadFile, DatabaseList, DatabaseCreateRequest, DatabaseDefinition, DatabaseDefinitionSaveRequest, DatabaseDefinitionSaved, DatabaseTables, DatabaseTableCreateRequest, DatabaseTableCreated, DatabaseRecords, DatabaseRecordsQuery, DatabaseTransactionRequest, DatabaseTransactionReceipt, WriteSync, WriteSyncCreateRequest, WriteSyncUpdateRequest, WriteSyncDetail, WriteSyncList, WriteSyncDeleted, WriteSyncDestinations, WriteSyncRun, WriteSyncRunList, WriteSyncRunQuery, WriteSyncExecution, ResourceVersionState, ResourceRevisionList, ResourceRevision, ResourceVersionRequest, ResourcePublishRequest, Fact, FactList, FactWriteRequest, SkillList, SkillContent, SkillWriteRequest, KnowledgeWriteResponse, OperationRunGroup, OperationRunQuery, Operation, OperationList, OperationListQuery, OperationSource, OperationSourceUpdateRequest, OperationUpdateRequest, OperationRunRequest, OperationRunStarted, OperationRunList, OperationRunOutput, DataFlow, DataFlowCreateRequest, DataFlowCommandRequest, DataFlowCommandResponse, Workspace, WorkspaceCreateRequest, WorkspaceDeleteResponse, WorkspaceList, WorkspaceUpdateRequest, AnswerRequest, AnswerResponse, PermuteClientOptions, PermuteRequestOptions, QueryRequest, SearchRequest, SourceDetail, CatalogTable, SourceList, CustomDatasetCreateRequest, DatasetDeleteResponse, DatasetResponse, FileDatasetCreateRequest, FileDatasetMetadataCreateRequest, FileDatasetResponse, DatasetRows, CustomDatasetResponse, DashboardSource, DashboardSourceUpdateRequest } from './types.js';
3
+ import type { BusinessAction, BusinessActionDetail, BusinessActionList, ActionCreateRequest, ActionDefinition, ActionDefinitionSaveRequest, ActionDefinitionSaved, ActionRequest, ActionReceipt, ActionPublicationRequest, ActionPublicationRequestInput, ActionPublicationRequestList, ActionPublicationDecision } from './types.js';
4
+ import type { ConnectorSession, ConnectorSessionCreated, ConnectorSessionCreateRequest, Database, AppPublicationRequest, AppPublicationRequestInput, AppPublicationRequestList, AppPublicationDecision, AppDraft, AppAccess, AppAddressSettings, AppAddressSetRequest, AppAccessSetRequest, AppDraftList, AppCreateRequest, AppUpdateRequest, AppDeleted, AppUploadsRequest, AppUploads, AppSiteSaveRequest, AppSourceFileQuery, AppSourceFileContent, AppGrants, AppGrantSetRequest, AppUploadFile, DatabaseList, DatabaseCreateRequest, DatabaseDefinition, DatabaseDefinitionSaveRequest, DatabaseDefinitionSaved, DatabaseTables, DatabaseTableCreateRequest, DatabaseTableCreated, DatabaseRecords, DatabaseRecordsQuery, DatabaseTransactionRequest, DatabaseTransactionReceipt, WriteSync, WriteSyncCreateRequest, WriteSyncUpdateRequest, WriteSyncDetail, WriteSyncList, WriteSyncDeleted, WriteSyncDestinations, WriteSyncRun, WriteSyncRunList, WriteSyncRunQuery, WriteSyncExecution, ResourceVersionState, ResourceRevisionList, ResourceRevision, ResourceVersionRequest, ResourcePublishRequest, Fact, FactList, FactWriteRequest, SkillList, SkillContent, SkillWriteRequest, KnowledgeWriteResponse, OperationRunGroup, OperationRunQuery, Operation, OperationList, OperationListQuery, OperationSource, OperationSourceUpdateRequest, OperationUpdateRequest, OperationRunRequest, OperationRunStarted, OperationRunList, OperationRunOutput, DataFlow, DataFlowCreateRequest, DataFlowCommandRequest, DataFlowCommandResponse, Workspace, WorkspaceCreateRequest, WorkspaceDeleteResponse, WorkspaceList, WorkspaceUpdateRequest, AnswerRequest, AnswerResponse, PermuteClientOptions, PermuteRequestOptions, QueryRequest, SearchRequest, SourceDetail, CatalogTable, SourceList, CustomDatasetCreateRequest, DatasetDeleteResponse, DatasetResponse, FileDatasetCreateRequest, FileDatasetMetadataCreateRequest, FileDatasetResponse, DatasetRows, CustomDatasetResponse, DashboardSource, DashboardSourceUpdateRequest } from './types.js';
4
5
  type DatasetWriteInput = {
5
6
  tables: Record<string, DatasetRows>;
6
7
  mode: 'replace';
@@ -19,7 +20,7 @@ type DatasetReader = (id: string, options?: PermuteRequestOptions) => Promise<Da
19
20
  export declare class PermuteDataset {
20
21
  private readonly writeTables;
21
22
  private readonly readDataset;
22
- readonly type: "custom";
23
+ readonly type: 'custom';
23
24
  private snapshot;
24
25
  constructor(snapshot: CustomDatasetResponse, writeTables: DatasetWriter, readDataset: DatasetReader);
25
26
  get data(): CustomDatasetResponse;
@@ -39,7 +40,7 @@ export declare class PermuteDataset {
39
40
  }
40
41
  export declare class PermuteFileDataset {
41
42
  private readonly readDataset;
42
- readonly type: "file";
43
+ readonly type: 'file';
43
44
  private snapshot;
44
45
  constructor(snapshot: FileDatasetResponse, readDataset: DatasetReader);
45
46
  get data(): FileDatasetResponse;
@@ -56,6 +57,19 @@ export interface SkillsClient {
56
57
  delete(path: string, options?: PermuteRequestOptions): Promise<KnowledgeWriteResponse>;
57
58
  }
58
59
  export declare class PermuteClient {
60
+ readonly permissions: {
61
+ update(permissionId: string, body: PermissionGrantUpdate, options?: PermuteRequestOptions): Promise<PermissionGrant>;
62
+ list(query?: PermissionGrantQuery, options?: PermuteRequestOptions): Promise<PermissionGrantList>;
63
+ create(body: PermissionGrantInput, options?: PermuteRequestOptions): Promise<PermissionGrant>;
64
+ delete(permissionId: string, options?: PermuteRequestOptions): Promise<PermissionGrantRevoked>;
65
+ inspect(body: PermissionInspectionInput, options?: PermuteRequestOptions): Promise<PermissionInspection>;
66
+ };
67
+ readonly accessRequests: {
68
+ create(body: AccessRequestInput, options?: PermuteRequestOptions): Promise<AccessRequest>;
69
+ list(query?: AccessRequestQuery, options?: PermuteRequestOptions): Promise<AccessRequestList>;
70
+ get(requestId: string, options?: PermuteRequestOptions): Promise<AccessRequest>;
71
+ decide(requestId: string, body: AccessRequestDecision, options?: PermuteRequestOptions): Promise<AccessRequest>;
72
+ };
59
73
  readonly revisions: {
60
74
  list(resourceId: string, options?: PermuteRequestOptions): Promise<ResourceRevisionList>;
61
75
  get(resourceId: string, revisionId: string, options?: PermuteRequestOptions): Promise<ResourceRevision>;
@@ -72,14 +86,22 @@ export declare class PermuteClient {
72
86
  readonly skills: SkillsClient;
73
87
  readonly organizationSkills: SkillsClient;
74
88
  readonly actions: {
89
+ requestPublication(actionId: string, body: ActionPublicationRequestInput, options?: PermuteRequestOptions): Promise<ActionPublicationRequest>;
90
+ publicationRequests(actionId: string, options?: PermuteRequestOptions): Promise<ActionPublicationRequestList>;
91
+ decidePublication(actionId: string, requestId: string, body: ActionPublicationDecision, options?: PermuteRequestOptions): Promise<ActionPublicationRequest>;
75
92
  list(options?: PermuteRequestOptions): Promise<BusinessActionList>;
76
93
  create(body: ActionCreateRequest, options?: PermuteRequestOptions): Promise<BusinessAction>;
77
- get(actionId: string, options?: PermuteRequestOptions): Promise<BusinessAction>;
94
+ get(actionId: string, options?: PermuteRequestOptions): Promise<BusinessActionDetail>;
78
95
  delete(actionId: string, options?: PermuteRequestOptions): Promise<BusinessAction>;
79
96
  definition(actionId: string, options?: PermuteRequestOptions): Promise<ActionDefinition>;
80
97
  saveDefinition(actionId: string, body: ActionDefinitionSaveRequest, options?: PermuteRequestOptions): Promise<ActionDefinitionSaved>;
81
98
  invoke(actionId: string, body: ActionRequest, options?: PermuteRequestOptions): Promise<ActionReceipt>;
82
99
  };
100
+ readonly emails: {
101
+ get(options?: PermuteRequestOptions): Promise<EmailSender>;
102
+ /** Only callable from Business Actions through platform.withStep(stepId). */
103
+ send(body: EmailSendRequest, options?: PermuteRequestOptions): Promise<EmailReceipt>;
104
+ };
83
105
  readonly databases: {
84
106
  list(options?: PermuteRequestOptions): Promise<DatabaseList>;
85
107
  create(body: DatabaseCreateRequest, options?: PermuteRequestOptions): Promise<Database>;
@@ -93,6 +115,9 @@ export declare class PermuteClient {
93
115
  transact(databaseId: string, body: DatabaseTransactionRequest, options?: PermuteRequestOptions): Promise<DatabaseTransactionReceipt>;
94
116
  };
95
117
  readonly apps: {
118
+ requestPublication(applicationId: string, body: AppPublicationRequestInput, options?: PermuteRequestOptions): Promise<AppPublicationRequest>;
119
+ publicationRequests(applicationId: string, options?: PermuteRequestOptions): Promise<AppPublicationRequestList>;
120
+ decidePublication(applicationId: string, requestId: string, body: AppPublicationDecision, options?: PermuteRequestOptions): Promise<AppPublicationRequest>;
96
121
  address(applicationId: string, options?: PermuteRequestOptions): Promise<AppAddressSettings>;
97
122
  setAddress(applicationId: string, body: AppAddressSetRequest, options?: PermuteRequestOptions): Promise<AppAddressSettings>;
98
123
  access(applicationId: string, options?: PermuteRequestOptions): Promise<AppAccess>;
@@ -172,7 +197,8 @@ export declare class PermuteClient {
172
197
  download: (datasetId: string, options?: PermuteRequestOptions) => Promise<string>;
173
198
  delete: (datasetId: string, options?: PermuteRequestOptions) => Promise<DatasetDeleteResponse>;
174
199
  };
175
- private readonly apiKey;
200
+ private readonly apiKey?;
201
+ private readonly accessToken?;
176
202
  private readonly baseUrl;
177
203
  /** Workspace selected for workspace-scoped API operations. */
178
204
  readonly workspaceId?: string;
@@ -191,12 +217,12 @@ export declare class PermuteClient {
191
217
  score?: number;
192
218
  sourceId?: string;
193
219
  title?: string;
194
- type: "record" | "document" | "table" | "text_block" | "unknown";
220
+ type: 'record' | 'document' | 'table' | 'text_block' | 'unknown';
195
221
  }[];
196
222
  meta: {
197
223
  candidateCount?: number;
198
224
  reranked: boolean;
199
- strategy: "semantic";
225
+ strategy: 'semantic';
200
226
  totalMs?: number;
201
227
  };
202
228
  }>;
@@ -222,18 +248,18 @@ export declare class PermuteClient {
222
248
  ref?: string;
223
249
  sourceId?: string;
224
250
  title?: string;
225
- type: "text" | "table" | "web" | "fact";
251
+ type: 'text' | 'table' | 'web' | 'fact';
226
252
  url?: string;
227
253
  }[];
228
254
  confidence?: {
229
- queryComplexity: "high" | "medium" | "low";
255
+ queryComplexity: 'high' | 'medium' | 'low';
230
256
  reason: string;
231
257
  score: number;
232
258
  };
233
259
  followUps?: string[];
234
260
  };
235
261
  startedAt?: string | null;
236
- status: "queued" | "running" | "completed" | "failed" | "cancelled";
262
+ status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';
237
263
  updatedAt?: string;
238
264
  }>;
239
265
  getAnswerJob: (answerJobId: string, options?: PermuteRequestOptions) => Promise<{
@@ -257,18 +283,18 @@ export declare class PermuteClient {
257
283
  ref?: string;
258
284
  sourceId?: string;
259
285
  title?: string;
260
- type: "text" | "table" | "web" | "fact";
286
+ type: 'text' | 'table' | 'web' | 'fact';
261
287
  url?: string;
262
288
  }[];
263
289
  confidence?: {
264
- queryComplexity: "high" | "medium" | "low";
290
+ queryComplexity: 'high' | 'medium' | 'low';
265
291
  reason: string;
266
292
  score: number;
267
293
  };
268
294
  followUps?: string[];
269
295
  };
270
296
  startedAt?: string | null;
271
- status: "queued" | "running" | "completed" | "failed" | "cancelled";
297
+ status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';
272
298
  updatedAt?: string;
273
299
  }>;
274
300
  withWorkspace(workspaceId: string): PermuteClient;
package/dist/client.js CHANGED
@@ -251,11 +251,14 @@ export class PermuteFileDataset {
251
251
  }
252
252
  }
253
253
  export class PermuteClient {
254
+ permissions;
255
+ accessRequests;
254
256
  revisions;
255
257
  facts;
256
258
  skills;
257
259
  organizationSkills;
258
260
  actions;
261
+ emails;
259
262
  databases;
260
263
  apps;
261
264
  connectorSessions;
@@ -267,17 +270,18 @@ export class PermuteClient {
267
270
  dashboards;
268
271
  datasets;
269
272
  apiKey;
273
+ accessToken;
270
274
  baseUrl;
271
275
  /** Workspace selected for workspace-scoped API operations. */
272
276
  workspaceId;
273
277
  defaultHeaders;
274
278
  fetchImpl;
275
279
  constructor(options) {
276
- if (!options.apiKey) {
280
+ if ((!options.apiKey && !options.accessToken) || (options.apiKey && options.accessToken)) {
277
281
  throw new PermuteApiError({
278
282
  status: 0,
279
283
  code: 'missing_api_key',
280
- message: 'apiKey is required',
284
+ message: 'Provide apiKey or accessToken',
281
285
  });
282
286
  }
283
287
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -289,10 +293,24 @@ export class PermuteClient {
289
293
  });
290
294
  }
291
295
  this.apiKey = options.apiKey;
296
+ this.accessToken = options.accessToken;
292
297
  this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
293
298
  this.workspaceId = options.workspaceId;
294
299
  this.defaultHeaders = options.headers ?? {};
295
300
  this.fetchImpl = fetchImpl.bind(globalThis);
301
+ this.permissions = {
302
+ update: this.bindMethod('permissionsUpdate', (request) => (permissionId, body, options) => request({ pathParams: { permissionId }, body }, options)),
303
+ list: this.bindMethod('permissionsList', (request) => (query, options) => request({ query }, options)),
304
+ create: this.bindMethod('permissionsCreate', (request) => (body, options) => request({ body }, options)),
305
+ delete: this.bindMethod('permissionsDelete', (request) => (permissionId, options) => request({ pathParams: { permissionId } }, options)),
306
+ inspect: this.bindMethod('permissionsInspect', (request) => (body, options) => request({ body }, options)),
307
+ };
308
+ this.accessRequests = {
309
+ create: this.bindMethod('accessRequestsCreate', (request) => (body, options) => request({ body }, options)),
310
+ list: this.bindMethod('accessRequestsList', (request) => (query, options) => request({ query }, options)),
311
+ get: this.bindMethod('accessRequestsGet', (request) => (requestId, options) => request({ pathParams: { requestId } }, options)),
312
+ decide: this.bindMethod('accessRequestsDecide', (request) => (requestId, body, options) => request({ pathParams: { requestId }, body }, options)),
313
+ };
296
314
  this.revisions = {
297
315
  list: this.bindMethod('resourceRevisionsList', (apiRequest) => (resourceId, options) => apiRequest({ pathParams: { resourceId } }, options)),
298
316
  get: this.bindMethod('resourceRevisionsGet', (apiRequest) => (resourceId, revisionId, options) => apiRequest({ pathParams: { resourceId, revisionId } }, options)),
@@ -315,6 +333,9 @@ export class PermuteClient {
315
333
  this.skills = skillsClient('skills');
316
334
  this.organizationSkills = skillsClient('organizationSkills');
317
335
  this.actions = {
336
+ requestPublication: this.bindMethod('actionsPublicationRequestsCreate', (apiRequest) => (actionId, body, options) => apiRequest({ pathParams: { actionId }, body }, options)),
337
+ publicationRequests: this.bindMethod('actionsPublicationRequestsList', (apiRequest) => (actionId, options) => apiRequest({ pathParams: { actionId } }, options)),
338
+ decidePublication: this.bindMethod('actionsPublicationRequestsDecide', (apiRequest) => (actionId, requestId, body, options) => apiRequest({ pathParams: { actionId, requestId }, body }, options)),
318
339
  list: this.bindMethod('actionsList', (apiRequest) => (options) => apiRequest({}, options)),
319
340
  create: this.bindMethod('actionsCreate', (apiRequest) => (body, options) => apiRequest({ body }, options)),
320
341
  get: this.bindMethod('actionsGet', (apiRequest) => (actionId, options) => apiRequest({ pathParams: { actionId } }, options)),
@@ -323,6 +344,10 @@ export class PermuteClient {
323
344
  saveDefinition: this.bindMethod('actionDefinitionSave', (apiRequest) => (actionId, body, options) => apiRequest({ pathParams: { actionId }, body }, options)),
324
345
  invoke: this.bindMethod('actionsInvoke', (apiRequest) => (actionId, body, options) => apiRequest({ pathParams: { actionId }, body }, options)),
325
346
  };
347
+ this.emails = {
348
+ get: this.bindMethod('emailsGet', (request) => (options) => request({}, options)),
349
+ send: this.bindMethod('emailsSend', (request) => (body, options) => request({ body }, options)),
350
+ };
326
351
  this.databases = {
327
352
  list: this.bindMethod('databasesList', (apiRequest) => (options) => apiRequest({}, options)),
328
353
  create: this.bindMethod('databasesCreate', (apiRequest) => (body, options) => apiRequest({ body }, options)),
@@ -336,6 +361,9 @@ export class PermuteClient {
336
361
  transact: this.bindMethod('databaseTransactionsCreate', (apiRequest) => (databaseId, body, options) => apiRequest({ pathParams: { databaseId }, body }, options)),
337
362
  };
338
363
  this.apps = {
364
+ requestPublication: this.bindMethod('appsPublicationRequestsCreate', (apiRequest) => (applicationId, body, options) => apiRequest({ pathParams: { applicationId }, body }, options)),
365
+ publicationRequests: this.bindMethod('appsPublicationRequestsList', (apiRequest) => (applicationId, options) => apiRequest({ pathParams: { applicationId } }, options)),
366
+ decidePublication: this.bindMethod('appsPublicationRequestsDecide', (apiRequest) => (applicationId, requestId, body, options) => apiRequest({ pathParams: { applicationId, requestId }, body }, options)),
339
367
  sourceFile: this.bindMethod('appsSourceFileGet', (apiRequest) => (applicationId, query, options) => apiRequest({ pathParams: { applicationId }, query }, options)),
340
368
  address: this.bindMethod('appsAddressGet', (apiRequest) => (applicationId, options) => apiRequest({ pathParams: { applicationId } }, options)),
341
369
  setAddress: this.bindMethod('appsAddressSet', (apiRequest) => (applicationId, body, options) => apiRequest({ pathParams: { applicationId }, body }, options)),
@@ -613,6 +641,7 @@ export class PermuteClient {
613
641
  }
614
642
  return new PermuteClient({
615
643
  apiKey: this.apiKey,
644
+ accessToken: this.accessToken,
616
645
  baseUrl: this.baseUrl,
617
646
  workspaceId,
618
647
  fetch: this.fetchImpl,
@@ -628,7 +657,7 @@ export class PermuteClient {
628
657
  const body = this.validateRequestBody(route, operationId, input.body);
629
658
  const query = this.validateRequestQuery(route, operationId, input.query);
630
659
  const headers = {
631
- Authorization: `Bearer ${this.apiKey}`,
660
+ Authorization: `Bearer ${this.accessToken ? await this.accessToken() : this.apiKey}`,
632
661
  ...this.defaultHeaders,
633
662
  ...options?.headers,
634
663
  };
package/dist/deploy.d.ts CHANGED
@@ -28,7 +28,7 @@ export declare function saveAppSource(client: PermuteClient, options: {
28
28
  deployment: {
29
29
  error: string | null;
30
30
  revisionId: string;
31
- status: "deploying" | "live" | "deleting" | "failed" | "deleted";
31
+ status: 'deploying' | 'live' | 'deleting' | 'failed' | 'deleted';
32
32
  url: string;
33
33
  } | null;
34
34
  description: string;