@deepraxis/cli 0.1.0-dev.48c1ce8 → 0.1.0-dev.4b66104

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.
Files changed (2) hide show
  1. package/dist/praxis.js +51 -34
  2. package/package.json +1 -1
package/dist/praxis.js CHANGED
@@ -11,7 +11,7 @@ var operations = [
11
11
  resource: "agent.agents",
12
12
  method: "list",
13
13
  summary: "List agents",
14
- description: "List the agents of the workspace behind your API key, newest first, in pages of at most 100 (default 20). Use it to find an agent id before creating a session; to read one agent use agents.retrieve, to see its history use agents.versions.list. Archived agents are hidden unless include_archived is true. Filter kind=personal for durable-computer agents or kind=business for per-session environments. Pass next_page from the response as page to read the next page; a null next_page means the end.",
14
+ description: "List the agents of the workspace behind your API key, newest first, in pages of at most 100 (default 20). Use it to find an agent id before creating a session; to read one agent use agents.retrieve, to see its history use agents.versions.list. Archived agents are hidden unless include_archived is true. Filter kind=personal for durable-computer agents or kind=service for per-session environments. Pass next_page from the response as page to read the next page; a null next_page means the end.",
15
15
  http: "GET",
16
16
  path: "/agent/v1/agents",
17
17
  streaming: "no",
@@ -57,7 +57,7 @@ var operations = [
57
57
  type: "string",
58
58
  enum: [
59
59
  "personal",
60
- "business"
60
+ "service"
61
61
  ],
62
62
  required: false,
63
63
  description: "Filter agents by their immutable kind, including agents created before kind was recorded."
@@ -141,10 +141,10 @@ across all toolsets allowed.`
141
141
  type: "string",
142
142
  enum: [
143
143
  "personal",
144
- "business"
144
+ "service"
145
145
  ],
146
146
  required: false,
147
- description: "Immutable agent kind. personal requires computer_id; business cannot bind a computer. Omit on create to infer from computer_id. On update, the same kind is ignored; changing kind or crossing its computer binding returns 400 invalid_request_error."
147
+ description: "Immutable agent kind. personal requires computer_id; service cannot bind a computer. Omit on create to infer from computer_id. On update, the same kind is ignored; changing kind or crossing its computer binding returns 400 invalid_request_error."
148
148
  },
149
149
  {
150
150
  name: "computer_id",
@@ -317,10 +317,10 @@ current version; omit to apply the update unconditionally.`
317
317
  type: "string",
318
318
  enum: [
319
319
  "personal",
320
- "business"
320
+ "service"
321
321
  ],
322
322
  required: false,
323
- description: "Immutable agent kind. personal requires computer_id; business cannot bind a computer. Omit on create to infer from computer_id. On update, the same kind is ignored; changing kind or crossing its computer binding returns 400 invalid_request_error."
323
+ description: "Immutable agent kind. personal requires computer_id; service cannot bind a computer. Omit on create to infer from computer_id. On update, the same kind is ignored; changing kind or crossing its computer binding returns 400 invalid_request_error."
324
324
  },
325
325
  {
326
326
  name: "computer_id",
@@ -395,7 +395,7 @@ current version; omit to apply the update unconditionally.`
395
395
  resource: "agent.agents.endUsers",
396
396
  method: "list",
397
397
  summary: "List End Users",
398
- description: `List users who have sessions or token issuance history on a business agent.
398
+ description: `List users who have sessions or token issuance history on a service agent.
399
399
 
400
400
  Ordered by last_active_at and external_user_id descending. q is a case-sensitive literal prefix, including underscores. limit is 1–100, default 20. Reuse next_page with the same organization, agent, q and limit. Preemptively blocked users without history do not appear. End-user credentials and inaccessible or personal agents return 404.`,
401
401
  http: "GET",
@@ -433,7 +433,7 @@ Ordered by last_active_at and external_user_id descending. q is a case-sensitive
433
433
  resource: "agent.agents.endUsers",
434
434
  method: "delete",
435
435
  summary: "Delete end-user data",
436
- description: `Delete a host application's end-user data from one business agent after explicit confirmation.
436
+ description: `Delete a host application's end-user data from one service agent after explicit confirmation.
437
437
 
438
438
  Develop only. Set confirm to the exact external_user_id; missing or mismatched confirmation returns 400. Returns 202 with a pending task id, not completion. Poll the deletion endpoint. Concurrent requests reuse the unfinished task; retry DELETE after failure to resume it. Tokens are revoked and the user is blocked before a seven-day recovery snapshot is verified. Sessions including child sessions, conversation data, grants and feedback are then removed. A pre-existing block remains; a temporary block is removed on success. Attachment metadata is recorded and File attachments are retained. No charge is introduced by this operation. Example: DELETE /agent/v1/agents/agent_example/end_users/customer_123?confirm=customer_123.`,
439
439
  http: "DELETE",
@@ -804,7 +804,7 @@ Own-face superset: Managed Agents has no persistent Computer attachment director
804
804
 
805
805
  Own-face extension: Managed Agents has no persistent Computer connection. Returns the public SDK sandbox_id, envd_access_token and template_id, plus the machine tier the computer is on now (light or heavy) and the lease that keeps it there (lease_id, lease_expires_at; lease_id is null when no lease exists). Keep the lease while the connection stays open: renew it about every 20 seconds (POST .../leases/{lease_id}/renew) and release it on close (DELETE .../leases/{lease_id}). An unrenewed lease simply expires, and the full machine is reclaimed only after that. Archived computers remain accessible; foreign or absent computers return 404. Never cache credentials.
806
806
 
807
- Connect to a computer with a caller-held lease. Omit the body or send {} to request light: the lightweight shell, or the heavy instance while it is running. Send {"need":"heavy"} to request full Linux for interactive programs; files are synchronized before the heavy connection is returned with tier heavy. Heavy running time counts toward the daily budget in seconds. Renew the lease while using the connection and release it with DELETE when finished. If the daily budget is exhausted, 429 COMPUTER_BUDGET_EXHAUSTED allows you to continue with need light.`,
807
+ Connect to a computer with a caller-held lease. Omit the body or send {} to request light: the lightweight shell, or the heavy instance while it is running. Send {"need":"heavy"} to request full Linux for interactive programs; files are synchronized before the heavy connection is returned with tier heavy. Renew the lease while using the connection and release it with DELETE when finished.`,
808
808
  http: "POST",
809
809
  path: "/agent/v1/computers/{computer_id}/connect",
810
810
  streaming: "no",
@@ -1413,7 +1413,7 @@ Includes expired and revoked grants; returns neither token nor token_id. Sorts b
1413
1413
  name: "agent_id",
1414
1414
  type: "string",
1415
1415
  required: false,
1416
- description: "Filter by business agent identifier (agent_ or agt_ prefix)."
1416
+ description: "Filter by service agent identifier (agent_ or agt_ prefix)."
1417
1417
  },
1418
1418
  {
1419
1419
  name: "external_user_id",
@@ -1439,9 +1439,9 @@ Includes expired and revoked grants; returns neither token nor token_id. Sorts b
1439
1439
  resource: "agent.embedTokens",
1440
1440
  method: "create",
1441
1441
  summary: "Create Embed Token",
1442
- description: `Issue a short-lived credential on your backend for an end user of a business agent.
1442
+ description: `Issue a short-lived credential on your backend for an end user of a service agent.
1443
1443
 
1444
- Requires an active business agent in your organization with an embed policy. Pins the requested version or the latest version and snapshots the policy environment, vaults and resources; metadata comes from the request. Blocked users cannot receive tokens. Keep your API key on the backend and pass only the returned token to the frontend. Every call creates a new grant; issuance is not idempotent. Set hosted to true to also receive hosted_url; redirect the user there within 60 seconds. The agent must have an identity_number. The URL fragment contains a single-use exchange credential, not the token. Omit hosted or set false for ordinary token issuance.`,
1444
+ Requires an active service agent in your organization with an embed policy. Pins the requested version or the latest version and snapshots the policy environment, vaults and resources; metadata comes from the request. Blocked users cannot receive tokens. Keep your API key on the backend and pass only the returned token to the frontend. Every call creates a new grant; issuance is not idempotent. Set hosted to true to also receive hosted_url; redirect the user there within 60 seconds. The agent must have an identity_number. The URL fragment contains a single-use exchange credential, not the token. Omit hosted or set false for ordinary token issuance.`,
1445
1445
  http: "POST",
1446
1446
  path: "/agent/v1/embed_tokens",
1447
1447
  streaming: "no",
@@ -1461,7 +1461,7 @@ Requires an active business agent in your organization with an embed policy. Pin
1461
1461
  name: "agent",
1462
1462
  type: "string",
1463
1463
  required: true,
1464
- description: "Business agent ID or identity_number from agent retrieval; it must belong to your organization and be active."
1464
+ description: "Service agent ID or identity_number from agent retrieval; it must belong to your organization and be active."
1465
1465
  },
1466
1466
  {
1467
1467
  name: "version",
@@ -1536,7 +1536,7 @@ No Authorization header is required. Send the browser Origin allowed by the agen
1536
1536
  name: "publishable_key",
1537
1537
  type: "string",
1538
1538
  required: true,
1539
- description: "Public key created by the business agent owner; safe to include in browser code."
1539
+ description: "Public key created by the service agent owner; safe to include in browser code."
1540
1540
  },
1541
1541
  {
1542
1542
  name: "visitor_secret",
@@ -6952,7 +6952,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
6952
6952
  name: "{column}",
6953
6953
  type: "string",
6954
6954
  required: false,
6955
- description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix."
6955
+ description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. Supported operators: eq (equal), neq (not equal; ne is not supported), gt/gte/lt/lte (comparisons), like (case-sensitive text pattern), ilike (case-insensitive text pattern), in (membership), is (null/boolean test), cs (contains), cd (contained by), and ov (array overlap). For like/ilike, * or % matches any sequence and _ matches one character, e.g. title=ilike.*spring*; URL-encode a literal % as %25. Use days=in.(1,2,3), title=is.null, active=is.true or active=is.false; is.not_null and is.unknown are also accepted (unknown means null). Negate a condition with not., e.g. title=not.eq.draft. Multiple filters are ANDed; use or=(title.eq.a,title.eq.b), and=(days.gte.1,days.lte.3), not.or=(...) or not.and=(...), with nested and(...) and or(...) groups as needed. cs/cd accept JSON objects or arrays on JSON fields; cs also accepts a JSON scalar. For array values or multi-link fields, use cs.{a,b}, cd.{a,b} or ov.{a,b}. JSON paths use -> for JSON and ->> for text, e.g. attributes->>has_onsen=eq.true or attributes->tags=cs.[1,2]; chain -> segments and end with ->> for text. Dot paths such as attributes.has_onsen are unsupported. Full-text, regex, range operators and any/all modifiers are unsupported."
6956
6956
  },
6957
6957
  {
6958
6958
  name: "and",
@@ -7000,7 +7000,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7000
7000
  name: "on_conflict",
7001
7001
  type: "string",
7002
7002
  required: false,
7003
- description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7003
+ description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7004
7004
  },
7005
7005
  {
7006
7006
  name: "columns",
@@ -7014,7 +7014,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7014
7014
  resource: "database.databases.rest",
7015
7015
  method: "retrieve",
7016
7016
  summary: "Select rows",
7017
- description: "Read matching rows with filters, selected columns and ordering. Returns at most 1000 rows per request, including when limit is omitted. Content-Range reports the actual returned interval and the total when count is requested. PATCH and DELETE are not subject to this read cap. Unlike Supabase, casts, aggregates, spread and join modifiers are unsupported. Each table supports up to 1,000,000 rows. Query budget: 8,000 ms with a shared 3,000,000-row safety ceiling. Create indexes on filtered or sorted fields, or narrow the request when it exceeds its budget. Synchronous SQLite aggregates use candidate-row throughput estimates before execution; deployed Workers freeze clocks during synchronous CPU work, so the timer is not a guaranteed server-side interrupt. Count preferences: without filters, exact, planned and estimated all use SQLite's exact b-tree count. With filters, exact counts within budget; planned skips counting and reports an unknown total (Content-Range: 0-24/*); estimated attempts exact counting only when the preflight budget allows it, otherwise reports an unknown total. Preference-Applied echoes the requested count mode. Error table: QUERY_CANCELED / PostgREST 57014 is HTTP 500, retryable=false: Query timed out: index filtered or sorted fields, or narrow the range. DATABASE_INVALID_STATE is HTTP 409 for operations on a deleting database. Cleared or nonexistent databases return DATABASE_NOT_FOUND / HTTP 404. The count is an HTTP Content-Range response header, not a JSON property. Praxis SDK/codemode methods return the body only; a page length is not a total unless you know all matches fit in that page.",
7017
+ description: "Read matching rows with filters, selected columns and ordering. Returns at most 1000 rows per request, including when limit is omitted. Content-Range reports the actual returned interval and the total when count is requested. PATCH and DELETE are not subject to this read cap. Unlike Supabase, casts, aggregates, spread and join modifiers are unsupported. Each table supports up to 1,000,000 rows. Query budget: 8,000 ms with a shared 3,000,000-row safety ceiling. Create indexes on filtered or sorted fields, or narrow the request when it exceeds its budget. Synchronous SQLite aggregates use candidate-row throughput estimates before execution; deployed Workers freeze clocks during synchronous CPU work, so the timer is not a guaranteed server-side interrupt. Count preferences: without filters, exact, planned and estimated all use SQLite's exact b-tree count. With filters, exact counts within budget; planned skips counting and reports an unknown total (Content-Range: 0-24/*); estimated attempts exact counting only when the preflight budget allows it, otherwise reports an unknown total. Preference-Applied echoes the requested count mode. Error table: QUERY_CANCELED / PostgREST 57014 is HTTP 500, retryable=false: Query timed out: index filtered or sorted fields, or narrow the range. DATABASE_INVALID_STATE is HTTP 409 for operations on a deleting database. Cleared or nonexistent databases return DATABASE_NOT_FOUND / HTTP 404. The count is an HTTP Content-Range response header, not a JSON property. Use praxis.database.count in the SDK or codemode to return { count: number | null }; a page length is not a total unless you know all matches fit in that page.",
7018
7018
  http: "GET",
7019
7019
  path: "/database/v1/databases/{database_id}/rest/{table}",
7020
7020
  streaming: "no",
@@ -7040,7 +7040,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7040
7040
  name: "{column}",
7041
7041
  type: "string",
7042
7042
  required: false,
7043
- description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix."
7043
+ description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. Supported operators: eq (equal), neq (not equal; ne is not supported), gt/gte/lt/lte (comparisons), like (case-sensitive text pattern), ilike (case-insensitive text pattern), in (membership), is (null/boolean test), cs (contains), cd (contained by), and ov (array overlap). For like/ilike, * or % matches any sequence and _ matches one character, e.g. title=ilike.*spring*; URL-encode a literal % as %25. Use days=in.(1,2,3), title=is.null, active=is.true or active=is.false; is.not_null and is.unknown are also accepted (unknown means null). Negate a condition with not., e.g. title=not.eq.draft. Multiple filters are ANDed; use or=(title.eq.a,title.eq.b), and=(days.gte.1,days.lte.3), not.or=(...) or not.and=(...), with nested and(...) and or(...) groups as needed. cs/cd accept JSON objects or arrays on JSON fields; cs also accepts a JSON scalar. For array values or multi-link fields, use cs.{a,b}, cd.{a,b} or ov.{a,b}. JSON paths use -> for JSON and ->> for text, e.g. attributes->>has_onsen=eq.true or attributes->tags=cs.[1,2]; chain -> segments and end with ->> for text. Dot paths such as attributes.has_onsen are unsupported. Full-text, regex, range operators and any/all modifiers are unsupported."
7044
7044
  },
7045
7045
  {
7046
7046
  name: "and",
@@ -7088,7 +7088,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7088
7088
  name: "on_conflict",
7089
7089
  type: "string",
7090
7090
  required: false,
7091
- description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7091
+ description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7092
7092
  },
7093
7093
  {
7094
7094
  name: "columns",
@@ -7102,7 +7102,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7102
7102
  resource: "database.databases.rest",
7103
7103
  method: "head",
7104
7104
  summary: "Count rows",
7105
- description: "Inspect the HTTP row count and range without retrieving row data; send Prefer: count=exact for a filtered count. Returns no body and does not fetch or serialize row data. A known count determines the interval using limit/offset or Range with a default and maximum page size of 1000. Without a count preference, or when the selected count mode cannot supply a total, Content-Range is */*. Singular Accept still validates page cardinality. Unlike Supabase, planned and estimated counts do not use PostgreSQL planner estimates. Count preferences: without filters, exact, planned and estimated all use SQLite's exact b-tree count. With filters, exact counts within budget; planned skips counting and reports an unknown total (Content-Range: 0-24/*); estimated attempts exact counting only when the preflight budget allows it, otherwise reports an unknown total. Preference-Applied echoes the requested count mode. Praxis SDK/codemode methods return only the empty body, not the Content-Range response header; use an HTTP client when you need that header.",
7105
+ description: "Inspect the HTTP row count and range without retrieving row data; send Prefer: count=exact for a filtered count. Returns no body and does not fetch or serialize row data. A known count determines the interval using limit/offset or Range with a default and maximum page size of 1000. Without a count preference, or when the selected count mode cannot supply a total, Content-Range is */*. Singular Accept still validates page cardinality. Unlike Supabase, planned and estimated counts do not use PostgreSQL planner estimates. Count preferences: without filters, exact, planned and estimated all use SQLite's exact b-tree count. With filters, exact counts within budget; planned skips counting and reports an unknown total (Content-Range: 0-24/*); estimated attempts exact counting only when the preflight budget allows it, otherwise reports an unknown total. Preference-Applied echoes the requested count mode. Use praxis.database.count in the SDK or codemode to return { count: number | null } from this header without retrieving rows.",
7106
7106
  http: "HEAD",
7107
7107
  path: "/database/v1/databases/{database_id}/rest/{table}",
7108
7108
  streaming: "no",
@@ -7128,7 +7128,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7128
7128
  name: "{column}",
7129
7129
  type: "string",
7130
7130
  required: false,
7131
- description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix."
7131
+ description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. Supported operators: eq (equal), neq (not equal; ne is not supported), gt/gte/lt/lte (comparisons), like (case-sensitive text pattern), ilike (case-insensitive text pattern), in (membership), is (null/boolean test), cs (contains), cd (contained by), and ov (array overlap). For like/ilike, * or % matches any sequence and _ matches one character, e.g. title=ilike.*spring*; URL-encode a literal % as %25. Use days=in.(1,2,3), title=is.null, active=is.true or active=is.false; is.not_null and is.unknown are also accepted (unknown means null). Negate a condition with not., e.g. title=not.eq.draft. Multiple filters are ANDed; use or=(title.eq.a,title.eq.b), and=(days.gte.1,days.lte.3), not.or=(...) or not.and=(...), with nested and(...) and or(...) groups as needed. cs/cd accept JSON objects or arrays on JSON fields; cs also accepts a JSON scalar. For array values or multi-link fields, use cs.{a,b}, cd.{a,b} or ov.{a,b}. JSON paths use -> for JSON and ->> for text, e.g. attributes->>has_onsen=eq.true or attributes->tags=cs.[1,2]; chain -> segments and end with ->> for text. Dot paths such as attributes.has_onsen are unsupported. Full-text, regex, range operators and any/all modifiers are unsupported."
7132
7132
  },
7133
7133
  {
7134
7134
  name: "and",
@@ -7176,7 +7176,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7176
7176
  name: "on_conflict",
7177
7177
  type: "string",
7178
7178
  required: false,
7179
- description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7179
+ description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7180
7180
  },
7181
7181
  {
7182
7182
  name: "columns",
@@ -7216,7 +7216,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7216
7216
  name: "{column}",
7217
7217
  type: "string",
7218
7218
  required: false,
7219
- description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix."
7219
+ description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. Supported operators: eq (equal), neq (not equal; ne is not supported), gt/gte/lt/lte (comparisons), like (case-sensitive text pattern), ilike (case-insensitive text pattern), in (membership), is (null/boolean test), cs (contains), cd (contained by), and ov (array overlap). For like/ilike, * or % matches any sequence and _ matches one character, e.g. title=ilike.*spring*; URL-encode a literal % as %25. Use days=in.(1,2,3), title=is.null, active=is.true or active=is.false; is.not_null and is.unknown are also accepted (unknown means null). Negate a condition with not., e.g. title=not.eq.draft. Multiple filters are ANDed; use or=(title.eq.a,title.eq.b), and=(days.gte.1,days.lte.3), not.or=(...) or not.and=(...), with nested and(...) and or(...) groups as needed. cs/cd accept JSON objects or arrays on JSON fields; cs also accepts a JSON scalar. For array values or multi-link fields, use cs.{a,b}, cd.{a,b} or ov.{a,b}. JSON paths use -> for JSON and ->> for text, e.g. attributes->>has_onsen=eq.true or attributes->tags=cs.[1,2]; chain -> segments and end with ->> for text. Dot paths such as attributes.has_onsen are unsupported. Full-text, regex, range operators and any/all modifiers are unsupported."
7220
7220
  },
7221
7221
  {
7222
7222
  name: "and",
@@ -7264,7 +7264,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7264
7264
  name: "on_conflict",
7265
7265
  type: "string",
7266
7266
  required: false,
7267
- description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7267
+ description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7268
7268
  },
7269
7269
  {
7270
7270
  name: "columns",
@@ -7284,7 +7284,7 @@ Own-face extension. Use a readable session and a run_id from its events. Each su
7284
7284
  summary: "Insert rows",
7285
7285
  description: `Insert rows into an existing table after defining its fields; at most 500 rows per request. Each request is atomic: any failure rolls back the entire batch. There are no transactions across requests.
7286
7286
  Rows are filled to the union of their keys with null; send Prefer: missing=default to use field defaults for missing keys.
7287
- The default is return=minimal: success returns HTTP 201 with an empty body. Send Prefer: return=representation to return the inserted rows. Unlike Supabase, upsert conflicts can target only id or one unique field, not a composite key. Each table supports up to 1,000,000 rows.`,
7287
+ The default is return=minimal: success returns HTTP 201 with an empty body. Send Prefer: return=representation to return the inserted rows. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. Unlike Supabase, upsert conflicts can target only id or one unique field, not a composite key. Each table supports up to 1,000,000 rows.`,
7288
7288
  http: "POST",
7289
7289
  path: "/database/v1/databases/{database_id}/rest/{table}",
7290
7290
  streaming: "no",
@@ -7310,7 +7310,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
7310
7310
  name: "{column}",
7311
7311
  type: "string",
7312
7312
  required: false,
7313
- description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix."
7313
+ description: "Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. Supported operators: eq (equal), neq (not equal; ne is not supported), gt/gte/lt/lte (comparisons), like (case-sensitive text pattern), ilike (case-insensitive text pattern), in (membership), is (null/boolean test), cs (contains), cd (contained by), and ov (array overlap). For like/ilike, * or % matches any sequence and _ matches one character, e.g. title=ilike.*spring*; URL-encode a literal % as %25. Use days=in.(1,2,3), title=is.null, active=is.true or active=is.false; is.not_null and is.unknown are also accepted (unknown means null). Negate a condition with not., e.g. title=not.eq.draft. Multiple filters are ANDed; use or=(title.eq.a,title.eq.b), and=(days.gte.1,days.lte.3), not.or=(...) or not.and=(...), with nested and(...) and or(...) groups as needed. cs/cd accept JSON objects or arrays on JSON fields; cs also accepts a JSON scalar. For array values or multi-link fields, use cs.{a,b}, cd.{a,b} or ov.{a,b}. JSON paths use -> for JSON and ->> for text, e.g. attributes->>has_onsen=eq.true or attributes->tags=cs.[1,2]; chain -> segments and end with ->> for text. Dot paths such as attributes.has_onsen are unsupported. Full-text, regex, range operators and any/all modifiers are unsupported."
7314
7314
  },
7315
7315
  {
7316
7316
  name: "and",
@@ -7358,7 +7358,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
7358
7358
  name: "on_conflict",
7359
7359
  type: "string",
7360
7360
  required: false,
7361
- description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7361
+ description: "POST upsert: id or one unique field with resolution=merge-duplicates|ignore-duplicates. With resolution=merge-duplicates, a conflicting row keeps columns omitted from the request; supplied values replace the whole field value (including JSON objects), and explicit null clears a nullable field. With resolution=ignore-duplicates, a conflicting row is left unchanged. Without a conflict, both modes insert a new row using field defaults for omitted fields. In a batch, a key present in another row is filled with null when omitted in this row unless missing=default is set; that null can overwrite a value during merge. With missing=default, omitted keys stay omitted for conflict merges (existing values are preserved); new rows use defaults, or null when no default exists. Explicit null never invokes a default. POST accepts an optional client id matching [A-Za-z0-9_-]{1,64}; omitted ids are generated. PATCH cannot change id."
7362
7362
  },
7363
7363
  {
7364
7364
  name: "columns",
@@ -7410,7 +7410,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
7410
7410
  resource: "database.databases.tables",
7411
7411
  method: "create",
7412
7412
  summary: "Create table",
7413
- description: "Creates a table together with its initial fields in one call and returns it (HTTP 201) with generated tbl_ and fld_ ids. name must match ^[a-z_][a-z0-9_]{0,62}$ and be unused in this database (duplicate: 409 UNIQUE_VIOLATION). fields is required and may be an empty array; fields can also be added later with databaseAddField. Limits: 50 tables per database, 64 fields per table, and 16 indexed or unique fields per table; exceeding one returns 400 LIMIT_EXCEEDED. Every row also has a system id column, which is not declared as a field. Insert data afterwards with databaseInsert. Unlike Supabase, define schema with this table API and the field APIs; PostgreSQL DDL and SQL migration files cannot be submitted. Each table supports up to 1,000,000 rows.",
7413
+ description: 'Creates a table together with its initial fields in one call and returns it (HTTP 201) with generated tbl_ and fld_ ids. name must match ^[a-z_][a-z0-9_]{0,62}$ and be unused in this database (duplicate: 409 UNIQUE_VIOLATION). fields is required and may be an empty array; fields can also be added later with databaseAddField. Limits: 50 tables per database, 64 fields per table, and 16 indexed or unique fields per table; exceeding one returns 400 LIMIT_EXCEEDED. Fields default to indexed:false. Set indexed:true explicitly for fields used in filters or ordering. Only indexed:true or unique:true consumes one of the 16 indexed-or-unique field slots; a field with both consumes one slot. Unique fields still consume a slot even with indexed:false. Existing fields are unchanged. Minimal field example: {"name":"notes","type":"string","indexed":false}. Every row also has a system id column, which is not declared as a field. Insert data afterwards with databaseInsert. Unlike Supabase, define schema with this table API and the field APIs; PostgreSQL DDL and SQL migration files cannot be submitted. Each table supports up to 1,000,000 rows.',
7414
7414
  http: "POST",
7415
7415
  path: "/database/v1/databases/{database_id}/tables",
7416
7416
  streaming: "no",
@@ -7531,7 +7531,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
7531
7531
  resource: "database.databases.tables.fields",
7532
7532
  method: "create",
7533
7533
  summary: "Add field",
7534
- description: "Adds one field to an existing table and returns the updated table (HTTP 201). Required inputs are name (lowercase letters, digits and underscores; id and names starting with _ are reserved) and type (string, integer, number, boolean, datetime, json or link); json needs options.schema and link needs options.linked_table_id and options.multiple. Adding a required field to a table that already has rows needs a default, otherwise the call fails with 400 VALIDATION_FAILED; a default is written into every existing row. Scalar fields are indexed by default, while json and link fields cannot be indexed. Limits: 64 fields and 16 indexed or unique fields per table (400 LIMIT_EXCEEDED). Unlike Supabase, schema evolution uses field definitions rather than ALTER TABLE statements or SQL migrations.",
7534
+ description: 'Adds one field to an existing table and returns the updated table (HTTP 201). Required inputs are name (lowercase letters, digits and underscores; id and names starting with _ are reserved) and type (string, integer, number, boolean, datetime, json or link); json needs options.schema and link needs options.linked_table_id and options.multiple. Adding a required field to a table that already has rows needs a default, otherwise the call fails with 400 VALIDATION_FAILED; a default is written into every existing row. Fields default to indexed:false. Set indexed:true explicitly for fields used in filters or ordering. Only indexed:true or unique:true consumes one of the 16 indexed-or-unique field slots; a field with both consumes one slot. Unique fields still consume a slot even with indexed:false. Existing fields are unchanged. Minimal field example: {"name":"notes","type":"string","indexed":false}. JSON and link fields cannot be indexed. Limits: 64 fields and 16 indexed or unique fields per table (400 LIMIT_EXCEEDED). Unlike Supabase, schema evolution uses field definitions rather than ALTER TABLE statements or SQL migrations.',
7535
7535
  http: "POST",
7536
7536
  path: "/database/v1/databases/{database_id}/tables/{table}/fields",
7537
7537
  streaming: "no",
@@ -21722,9 +21722,13 @@ class Transport {
21722
21722
  };
21723
21723
  }
21724
21724
  async request(operation, options = {}) {
21725
+ return (await this.requestWithResponse(operation, options)).data;
21726
+ }
21727
+ async requestWithResponse(operation, options = {}) {
21725
21728
  const scope = this.scope(options, false);
21726
21729
  try {
21727
- return (await abortable(operation(scope.options), scope.signal)).data;
21730
+ const result = await abortable(operation(scope.options), scope.signal);
21731
+ return { data: result.data, response: result.response };
21728
21732
  } finally {
21729
21733
  scope.close();
21730
21734
  }
@@ -21929,12 +21933,25 @@ async function publish(client2, input) {
21929
21933
  };
21930
21934
  }
21931
21935
 
21936
+ // ../../packages/sdk/typescript/src/helpers/database-count.ts
21937
+ async function count(transport, input) {
21938
+ const { response } = await transport.requestWithResponse(databaseHead, {
21939
+ path: { database_id: input.database_id, table: input.table },
21940
+ query: input.filters,
21941
+ headers: { Prefer: `count=${input.count ?? "exact"}` }
21942
+ });
21943
+ const total = response.headers.get("Content-Range")?.split("/")[1];
21944
+ return { count: total === undefined || total === "*" ? null : Number(total) };
21945
+ }
21946
+
21932
21947
  // ../../packages/sdk/typescript/src/core/client.ts
21933
21948
  class Praxis {
21934
21949
  constructor(options) {
21935
21950
  const transport = new Transport(options);
21936
21951
  for (const [name, create] of Object.entries(resourceFactories)) {
21937
21952
  const resource = create(transport);
21953
+ if (name === "database")
21954
+ Object.assign(resource, { count: (input) => count(transport, input) });
21938
21955
  if (name === "application")
21939
21956
  Object.assign(resource, { publish: (input) => publish(this, input) });
21940
21957
  Object.defineProperty(this, name, { value: resource, enumerable: true });
@@ -23066,7 +23083,7 @@ function plain(value) {
23066
23083
  }
23067
23084
 
23068
23085
  // src/output/human.ts
23069
- var count = (n, noun) => `${n} ${noun}${n === 1 ? "" : "s"}`;
23086
+ var count3 = (n, noun) => `${n} ${noun}${n === 1 ? "" : "s"}`;
23070
23087
  function identity(result, ctx) {
23071
23088
  const op = "op" in result ? result.op : undefined;
23072
23089
  const split = op?.lastIndexOf(".") ?? -1;
@@ -23154,7 +23171,7 @@ function objectView(data, resource, id, ctx, paint) {
23154
23171
  return v.map(scalar).map(plain).join(", ");
23155
23172
  folded = true;
23156
23173
  const preview = v.slice(0, 3).map((item) => record(item).id ?? record(item).name).filter((x) => x !== undefined).map((x) => plain(scalar(x)));
23157
- return `${count(v.length, "item")}${preview.length ? ` (${preview.join(", ")})` : ""}`;
23174
+ return `${count3(v.length, "item")}${preview.length ? ` (${preview.join(", ")})` : ""}`;
23158
23175
  }
23159
23176
  if (v !== null && typeof v === "object") {
23160
23177
  if (depth >= 1) {
@@ -23195,7 +23212,7 @@ function renderHuman(result, ctx) {
23195
23212
  return {
23196
23213
  stdout: result.items.length ? table(result.items, ctx, out) : out.dim(`No ${plain(resource)}${/(s|x|ch|sh)$/.test(resource) ? "es" : "s"}.`) + `
23197
23214
  `,
23198
- stderr: err.dim(`${result.total !== undefined ? `${result.items.length} of ${result.total} items` : count(result.items.length, "item")}${result.nextCursor ? ` · next: ${ctx.nextCommand ?? "praxis --help"}` : ""}`) + `
23215
+ stderr: err.dim(`${result.total !== undefined ? `${result.items.length} of ${result.total} items` : count3(result.items.length, "item")}${result.nextCursor ? ` · next: ${ctx.nextCommand ?? "praxis --help"}` : ""}`) + `
23199
23216
  `
23200
23217
  };
23201
23218
  case "object": {
@@ -23475,7 +23492,7 @@ function startProgress(ctx, write = (text) => writeOutput({ stderr: text })) {
23475
23492
  }
23476
23493
 
23477
23494
  // src/main.ts
23478
- var version = "0.1.0-dev.48c1ce8";
23495
+ var version = "0.1.0-dev.4b66104";
23479
23496
  var commands = commandTree(operations);
23480
23497
  var manual = [["login"], ["logout"], ["whoami"], ["org", "list"], ["org", "switch"], ["api"], ["skill"]];
23481
23498
  function route(argv) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepraxis/cli",
3
- "version": "0.1.0-dev.48c1ce8",
3
+ "version": "0.1.0-dev.4b66104",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "praxis": "dist/praxis.js"