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.
- package/dist/index.js +141 -12
- 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: '
|
|
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: '
|
|
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:
|
|
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:
|
|
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
|