sim 2.1.0-preview.29.1 → 2.1.0-preview.33.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.
Files changed (2) hide show
  1. package/dist/index.js +141 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6579,6 +6579,24 @@ var V2_OPERATIONS = {
6579
6579
  responseMode: "json",
6580
6580
  summary: "Cancel Workflow Run"
6581
6581
  },
6582
+ chat: {
6583
+ method: "POST",
6584
+ path: "/api/v2/chat",
6585
+ pathParams: [],
6586
+ responseMode: "json",
6587
+ body: {
6588
+ workspaceId: {
6589
+ kind: "string",
6590
+ required: true,
6591
+ describe: "Workspace the conversation runs in."
6592
+ },
6593
+ message: { kind: "string", required: true, describe: "The message to send to Sim." },
6594
+ conversationId: {
6595
+ kind: "string",
6596
+ describe: "Conversation to continue; a new one starts when omitted."
6597
+ }
6598
+ }
6599
+ },
6582
6600
  completeFileUpload: {
6583
6601
  method: "POST",
6584
6602
  path: "/api/v2/files/uploads/[uploadId]/complete",
@@ -9044,7 +9062,7 @@ var V2_OPERATIONS = {
9044
9062
  workspaceId: { kind: "string", required: true, describe: "Unique workspace identifier." },
9045
9063
  predicate: {
9046
9064
  kind: "unknown",
9047
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
9065
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
9048
9066
  },
9049
9067
  sort: { kind: "array", describe: "Ordered table-row sort specification." },
9050
9068
  limit: {
@@ -9065,7 +9083,7 @@ var V2_OPERATIONS = {
9065
9083
  workspaceId: { kind: "string", required: true, describe: "Unique workspace identifier." },
9066
9084
  predicate: {
9067
9085
  kind: "unknown",
9068
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
9086
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
9069
9087
  }
9070
9088
  }
9071
9089
  },
@@ -10193,6 +10211,7 @@ import { existsSync as existsSync2, readFileSync as readFileSync3, readSync } fr
10193
10211
  // src/contract/commands.ts
10194
10212
  var TABLE_NAME_HELP = "Identifier: letters, numbers, and underscores; cannot start with a number";
10195
10213
  var TABLE_FILTER_HELP = 'Predicate: {"all":[{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull';
10214
+ var TABLE_READ_FILTER_HELP = 'Condition: {"field":"status","op":"eq","value":"active"}. Groups: {"all":[{"field":"status","op":"eq","value":"active"}]} or {"any":[{"field":"status","op":"eq","value":"active"}]}; group entries may also be nested groups. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull';
10196
10215
  var TABLE_SORT_HELP = 'Ordered sort keys: [{"field":"createdAt","direction":"desc"}] (direction: asc or desc)';
10197
10216
  var CUSTOM_TOOL_SCHEMA_HELP = 'OpenAI function schema: {"type":"function","function":{"name":"...","parameters":{"type":"object","properties":{}}}}';
10198
10217
  var FOLDER_PATH_INPUT = {
@@ -10231,6 +10250,7 @@ function moveResource(command, resource) {
10231
10250
  };
10232
10251
  }
10233
10252
  var CLI_CONTRACT = {
10253
+ chat: { hidden: true },
10234
10254
  createCredentialConnection: { hidden: true },
10235
10255
  createServiceAccountCredential: { hidden: true },
10236
10256
  getBillingStatus: {
@@ -10431,7 +10451,7 @@ var CLI_CONTRACT = {
10431
10451
  queryRows: {
10432
10452
  command: "tables rows query",
10433
10453
  flags: {
10434
- predicate: { name: "filter", json: true, describe: TABLE_FILTER_HELP },
10454
+ predicate: { name: "filter", json: true, describe: TABLE_READ_FILTER_HELP },
10435
10455
  sort: { json: true, describe: TABLE_SORT_HELP }
10436
10456
  },
10437
10457
  expand: "data"
@@ -10859,7 +10879,7 @@ var CLI_CONTRACT = {
10859
10879
  name: "filter",
10860
10880
  renamedFrom: ["predicate"],
10861
10881
  json: true,
10862
- describe: TABLE_FILTER_HELP
10882
+ describe: TABLE_READ_FILTER_HELP
10863
10883
  }
10864
10884
  }
10865
10885
  },
@@ -11655,21 +11675,129 @@ function attachCredentialCommands(program2) {
11655
11675
  credentials.command("reconnect").argument("<credentialId>", "Existing OAuth credential to re-authorize").description("Create a short-lived link for reconnecting an OAuth credential").action((credentialId, _options, command) => createConnectionLink(command, { credentialId }));
11656
11676
  }
11657
11677
 
11658
- // src/commands/protocol/files-get.ts
11659
- import { once as once2 } from "node:events";
11660
- import { createWriteStream } from "node:fs";
11661
- import { link, lstat, mkdtemp, readlink, rename, rm } from "node:fs/promises";
11662
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
11663
- import { Readable } from "node:stream";
11664
- import { pipeline } from "node:stream/promises";
11665
-
11666
11678
  // src/commands/protocol/result.ts
11667
11679
  function printProtocolResult(format, result) {
11668
11680
  const fields = Object.entries(result).map(([key, value]) => [key, text(value)]);
11669
11681
  printRecord(format, fields, result);
11670
11682
  }
11671
11683
 
11684
+ // src/commands/protocol/chat.ts
11685
+ function parseChatStreamLine(line) {
11686
+ const trimmed = line.trim();
11687
+ if (!trimmed)
11688
+ return;
11689
+ try {
11690
+ return JSON.parse(trimmed);
11691
+ } catch {
11692
+ throw new SimApiError("Chat stream returned malformed data", 0);
11693
+ }
11694
+ }
11695
+ async function readChatStream(response, onChunk) {
11696
+ if (!response.body) {
11697
+ throw new SimApiError("Chat stream ended without a response body", 0);
11698
+ }
11699
+ const reader = response.body.getReader();
11700
+ const decoder = new TextDecoder;
11701
+ let buffer = "";
11702
+ let finalResult;
11703
+ const processLine = (line) => {
11704
+ const event = parseChatStreamLine(line);
11705
+ if (!event || event.type === "heartbeat")
11706
+ return;
11707
+ if (event.type === "chunk") {
11708
+ if (event.content)
11709
+ onChunk(sanitize(event.content));
11710
+ return;
11711
+ }
11712
+ if (event.type === "error") {
11713
+ throw new SimApiError(event.error || "Chat request failed", 0);
11714
+ }
11715
+ if (event.type === "final") {
11716
+ finalResult = event.data;
11717
+ return;
11718
+ }
11719
+ throw new SimApiError("Chat stream returned an unknown event", 0);
11720
+ };
11721
+ try {
11722
+ while (true) {
11723
+ const { done, value } = await reader.read();
11724
+ if (done)
11725
+ break;
11726
+ buffer += decoder.decode(value, { stream: true });
11727
+ const lines = buffer.split(`
11728
+ `);
11729
+ buffer = lines.pop() ?? "";
11730
+ for (const line of lines) {
11731
+ processLine(line);
11732
+ }
11733
+ }
11734
+ buffer += decoder.decode();
11735
+ processLine(buffer);
11736
+ if (!finalResult) {
11737
+ throw new SimApiError("Chat stream ended without a final result", 0);
11738
+ }
11739
+ return finalResult;
11740
+ } finally {
11741
+ reader.releaseLock();
11742
+ }
11743
+ }
11744
+ function attachChat(program2) {
11745
+ program2.command("chat").description("Ask Sim and print the reply").argument("<message>", "What to ask Sim").option("-c, --conversation <id>", "Continue the conversation with this ID").addHelpText("after", `
11746
+ Each turn prints the reply on stdout and the conversation ID on stderr; pass
11747
+ that ID back with -c to continue the same conversation. With --output json or
11748
+ yaml the reply is not streamed — the finished result is printed as one
11749
+ document, conversation ID included.
11750
+
11751
+ Examples:
11752
+ $ sim chat "What workflows do I have?"
11753
+ $ sim chat -c 3f2a… "Which of those run on a schedule?"
11754
+ $ sim --output json chat "Summarize yesterday's failed runs" | jq -r '.content'
11755
+ `).action(async (message, options, command) => {
11756
+ const { client, profile } = clientFrom(command);
11757
+ const workspaceId = client.requireWorkspace();
11758
+ const response = await client.requestRaw(V2_OPERATIONS.chat.path, {
11759
+ method: "POST",
11760
+ body: {
11761
+ workspaceId,
11762
+ message,
11763
+ ...options.conversation ? { conversationId: options.conversation } : {}
11764
+ },
11765
+ headers: { accept: "application/x-ndjson" }
11766
+ });
11767
+ const streaming = profile.output === "table" || profile.output === "text";
11768
+ let streamed = "";
11769
+ const result = await readChatStream(response, (content2) => {
11770
+ if (!streaming)
11771
+ return;
11772
+ streamed += content2;
11773
+ process.stdout.write(content2);
11774
+ });
11775
+ if (!streaming) {
11776
+ printProtocolResult(profile.output, result);
11777
+ return;
11778
+ }
11779
+ const content = sanitize(result.content ?? "");
11780
+ if (content.startsWith(streamed) && content.length > streamed.length) {
11781
+ process.stdout.write(content.slice(streamed.length));
11782
+ streamed = content;
11783
+ }
11784
+ if (streamed.length > 0 && !streamed.endsWith(`
11785
+ `)) {
11786
+ process.stdout.write(`
11787
+ `);
11788
+ }
11789
+ process.stderr.write(`${source_default.dim(`conversation: ${result.conversationId}`)}
11790
+ `);
11791
+ });
11792
+ }
11793
+
11672
11794
  // src/commands/protocol/files-get.ts
11795
+ import { once as once2 } from "node:events";
11796
+ import { createWriteStream } from "node:fs";
11797
+ import { link, lstat, mkdtemp, readlink, rename, rm } from "node:fs/promises";
11798
+ import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
11799
+ import { Readable } from "node:stream";
11800
+ import { pipeline } from "node:stream/promises";
11673
11801
  function writeFailure(path, error) {
11674
11802
  if (isRequestTimeout(error)) {
11675
11803
  return new SimApiError(`Downloading ${path} timed out. ${RAISE_TIMEOUT_HINT}`, 0);
@@ -13051,6 +13179,7 @@ function attachProtocolCommands(program2) {
13051
13179
  attachWorkflowRunFollow(workflows);
13052
13180
  attachWorkflowRunWait(group(workflows, "runs"));
13053
13181
  attachLogsFollow(group(program2, "logs"));
13182
+ attachChat(program2);
13054
13183
  }
13055
13184
 
13056
13185
  // src/terminal/secret-input.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sim",
3
- "version": "2.1.0-preview.29.1",
3
+ "version": "2.1.0-preview.33.1",
4
4
  "description": "Sim CLI - talk to the Sim API from your terminal",
5
5
  "type": "module",
6
6
  "bin": {