sim 2.1.0-preview.30.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 +136 -8
  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",
@@ -10232,6 +10250,7 @@ function moveResource(command, resource) {
10232
10250
  };
10233
10251
  }
10234
10252
  var CLI_CONTRACT = {
10253
+ chat: { hidden: true },
10235
10254
  createCredentialConnection: { hidden: true },
10236
10255
  createServiceAccountCredential: { hidden: true },
10237
10256
  getBillingStatus: {
@@ -11656,21 +11675,129 @@ function attachCredentialCommands(program2) {
11656
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 }));
11657
11676
  }
11658
11677
 
11659
- // src/commands/protocol/files-get.ts
11660
- import { once as once2 } from "node:events";
11661
- import { createWriteStream } from "node:fs";
11662
- import { link, lstat, mkdtemp, readlink, rename, rm } from "node:fs/promises";
11663
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
11664
- import { Readable } from "node:stream";
11665
- import { pipeline } from "node:stream/promises";
11666
-
11667
11678
  // src/commands/protocol/result.ts
11668
11679
  function printProtocolResult(format, result) {
11669
11680
  const fields = Object.entries(result).map(([key, value]) => [key, text(value)]);
11670
11681
  printRecord(format, fields, result);
11671
11682
  }
11672
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
+
11673
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";
11674
11801
  function writeFailure(path, error) {
11675
11802
  if (isRequestTimeout(error)) {
11676
11803
  return new SimApiError(`Downloading ${path} timed out. ${RAISE_TIMEOUT_HINT}`, 0);
@@ -13052,6 +13179,7 @@ function attachProtocolCommands(program2) {
13052
13179
  attachWorkflowRunFollow(workflows);
13053
13180
  attachWorkflowRunWait(group(workflows, "runs"));
13054
13181
  attachLogsFollow(group(program2, "logs"));
13182
+ attachChat(program2);
13055
13183
  }
13056
13184
 
13057
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.30.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": {