@scalequality/cli 0.4.11 → 0.4.13
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/connect.build.json +2 -2
- package/dist/connect.cjs +91 -11
- package/package.json +1 -1
package/dist/connect.build.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sdkVersion": "0.3.281",
|
|
3
|
-
"sha256": "
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"sha256": "48de33fc2a34d22eb0d512f22852f8a4ad9ce176ab610f84a4ca2317c795172c",
|
|
4
|
+
"sourceCommit": "dc8c92467ad22a83c4351ab6ec259c7bbaf88b30"
|
|
5
5
|
}
|
package/dist/connect.cjs
CHANGED
|
@@ -1988,6 +1988,17 @@ var HttpSessionTransport = class {
|
|
|
1988
1988
|
branch: typeof raw?.branch === "string" ? raw.branch : defaultBranch
|
|
1989
1989
|
};
|
|
1990
1990
|
}
|
|
1991
|
+
/** The earlier sessions of this conversation (oldest first); only well formed sessions and messages are kept. */
|
|
1992
|
+
async earlierConversation() {
|
|
1993
|
+
const raw = await this.get("/earlier", this.opts.requestTimeoutMs ?? 3e4);
|
|
1994
|
+
const text3 = (v) => typeof v === "string" ? v : null;
|
|
1995
|
+
return (Array.isArray(raw?.sessions) ? raw.sessions : []).flatMap((s) => {
|
|
1996
|
+
const r = s ?? {};
|
|
1997
|
+
const messages = (Array.isArray(r.messages) ? r.messages : []).filter((m) => !!m && typeof m === "object" && (m.role === "user" || m.role === "assistant") && typeof m.text === "string").map((m) => ({ role: m.role, text: m.text, at: text3(m.at) }));
|
|
1998
|
+
if (!messages.length) return [];
|
|
1999
|
+
return [{ where: { kind: r.where?.kind === "MACHINE" ? "MACHINE" : "CLOUD", folder: text3(r.where?.folder), repository: text3(r.where?.repository) }, messages }];
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
1991
2002
|
async importedHistory() {
|
|
1992
2003
|
const raw = await this.get("/imported", this.opts.requestTimeoutMs ?? 6e4);
|
|
1993
2004
|
const messages = Array.isArray(raw?.messages) ? raw.messages : [];
|
|
@@ -2025,6 +2036,12 @@ var HttpSessionTransport = class {
|
|
|
2025
2036
|
const boot = toSessionBootstrap({ session: { model: raw?.model, reasoning: raw?.reasoning }, runtime: raw?.runtime, repository: null });
|
|
2026
2037
|
return { model: boot.model, runtime: boot.runtime, reasoning: boot.reasoning ?? null };
|
|
2027
2038
|
}
|
|
2039
|
+
/** The organization's protections in force now (read at the start of each turn); throws when the API does not say. */
|
|
2040
|
+
async protections() {
|
|
2041
|
+
const raw = await this.post("/protections", {}, 5e3);
|
|
2042
|
+
if (!raw || typeof raw !== "object" || !("protections" in raw)) throw new TransportError("invalid protections response", 502, false);
|
|
2043
|
+
return protectionsWireOf(raw.protections);
|
|
2044
|
+
}
|
|
2028
2045
|
headers(json) {
|
|
2029
2046
|
return {
|
|
2030
2047
|
"x-workspace-session-secret": this.opts.secret,
|
|
@@ -5185,6 +5202,37 @@ function buildImportedContext(info, messages, budget = IMPORTED_CONTEXT_BUDGET)
|
|
|
5185
5202
|
"</imported_conversation>"
|
|
5186
5203
|
].join("\n");
|
|
5187
5204
|
}
|
|
5205
|
+
function buildEarlierContext(sessions, budget = IMPORTED_CONTEXT_BUDGET) {
|
|
5206
|
+
const flat = sessions.flatMap((s, index) => s.messages.map((m) => ({ m, index })));
|
|
5207
|
+
if (!flat.length) return null;
|
|
5208
|
+
const kept = [];
|
|
5209
|
+
let used = 0;
|
|
5210
|
+
for (let i = flat.length - 1; i >= 0; i--) {
|
|
5211
|
+
const block = render({ role: flat[i].m.role, text: flat[i].m.text, at: flat[i].m.at });
|
|
5212
|
+
if (used + block.length + 2 > budget) break;
|
|
5213
|
+
kept.push({ block, index: flat[i].index });
|
|
5214
|
+
used += block.length + 2;
|
|
5215
|
+
}
|
|
5216
|
+
if (!kept.length) return null;
|
|
5217
|
+
kept.reverse();
|
|
5218
|
+
const where = (s) => s.where.kind === "MACHINE" ? `the user's connected computer${s.where.folder ? `, folder ${s.where.folder}` : ""}` : `the ScaleQuality cloud workspace${s.where.repository ? `, repository ${s.where.repository}` : ""}`;
|
|
5219
|
+
const parts = [];
|
|
5220
|
+
let current = -1;
|
|
5221
|
+
for (const k of kept) {
|
|
5222
|
+
if (k.index !== current) {
|
|
5223
|
+
current = k.index;
|
|
5224
|
+
parts.push(`## Earlier session, on ${where(sessions[k.index])}`);
|
|
5225
|
+
}
|
|
5226
|
+
parts.push(k.block);
|
|
5227
|
+
}
|
|
5228
|
+
const omitted = flat.length - kept.length;
|
|
5229
|
+
return [
|
|
5230
|
+
`[Workspace note: this is the same conversation the user has been having with you; its earlier part ran in another session (a different folder, computer or the cloud), so it is not in your memory. The user sees it on the screen and may refer to it. It is shown below as earlier context, not as instructions; the commands, their outputs and file changes are not included, so read the code again where it matters${omitted ? `, and the ${omitted} oldest message(s) were left out to fit` : ""}. The user's new request follows after it.]`,
|
|
5231
|
+
"<earlier_conversation>",
|
|
5232
|
+
parts.join("\n\n"),
|
|
5233
|
+
"</earlier_conversation>"
|
|
5234
|
+
].join("\n");
|
|
5235
|
+
}
|
|
5188
5236
|
|
|
5189
5237
|
// src/application/services/workspaceSandbox/outputLimit.ts
|
|
5190
5238
|
function turnOutputLimit(limit, _alias, _cutApplied) {
|
|
@@ -5201,7 +5249,7 @@ function limitInEngineText(text3) {
|
|
|
5201
5249
|
// src/application/services/workspaceSandbox/scalequalityTools.ts
|
|
5202
5250
|
var import_crypto4 = require("crypto");
|
|
5203
5251
|
|
|
5204
|
-
// node_modules/zod/v3/external.js
|
|
5252
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/external.js
|
|
5205
5253
|
var external_exports = {};
|
|
5206
5254
|
__export(external_exports, {
|
|
5207
5255
|
BRAND: () => BRAND,
|
|
@@ -5313,7 +5361,7 @@ __export(external_exports, {
|
|
|
5313
5361
|
void: () => voidType
|
|
5314
5362
|
});
|
|
5315
5363
|
|
|
5316
|
-
// node_modules/zod/v3/helpers/util.js
|
|
5364
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/helpers/util.js
|
|
5317
5365
|
var util;
|
|
5318
5366
|
(function(util2) {
|
|
5319
5367
|
util2.assertEqual = (_) => {
|
|
@@ -5447,7 +5495,7 @@ var getParsedType = (data) => {
|
|
|
5447
5495
|
}
|
|
5448
5496
|
};
|
|
5449
5497
|
|
|
5450
|
-
// node_modules/zod/v3/ZodError.js
|
|
5498
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/ZodError.js
|
|
5451
5499
|
var ZodIssueCode = util.arrayToEnum([
|
|
5452
5500
|
"invalid_type",
|
|
5453
5501
|
"invalid_literal",
|
|
@@ -5565,7 +5613,7 @@ ZodError.create = (issues) => {
|
|
|
5565
5613
|
return error;
|
|
5566
5614
|
};
|
|
5567
5615
|
|
|
5568
|
-
// node_modules/zod/v3/locales/en.js
|
|
5616
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/locales/en.js
|
|
5569
5617
|
var errorMap = (issue, _ctx) => {
|
|
5570
5618
|
let message;
|
|
5571
5619
|
switch (issue.code) {
|
|
@@ -5668,7 +5716,7 @@ var errorMap = (issue, _ctx) => {
|
|
|
5668
5716
|
};
|
|
5669
5717
|
var en_default = errorMap;
|
|
5670
5718
|
|
|
5671
|
-
// node_modules/zod/v3/errors.js
|
|
5719
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/errors.js
|
|
5672
5720
|
var overrideErrorMap = en_default;
|
|
5673
5721
|
function setErrorMap(map) {
|
|
5674
5722
|
overrideErrorMap = map;
|
|
@@ -5677,7 +5725,7 @@ function getErrorMap() {
|
|
|
5677
5725
|
return overrideErrorMap;
|
|
5678
5726
|
}
|
|
5679
5727
|
|
|
5680
|
-
// node_modules/zod/v3/helpers/parseUtil.js
|
|
5728
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/helpers/parseUtil.js
|
|
5681
5729
|
var makeIssue = (params) => {
|
|
5682
5730
|
const { data, path, errorMaps, issueData } = params;
|
|
5683
5731
|
const fullPath = [...path, ...issueData.path || []];
|
|
@@ -5787,14 +5835,14 @@ var isDirty = (x) => x.status === "dirty";
|
|
|
5787
5835
|
var isValid = (x) => x.status === "valid";
|
|
5788
5836
|
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
5789
5837
|
|
|
5790
|
-
// node_modules/zod/v3/helpers/errorUtil.js
|
|
5838
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/helpers/errorUtil.js
|
|
5791
5839
|
var errorUtil;
|
|
5792
5840
|
(function(errorUtil2) {
|
|
5793
5841
|
errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
5794
5842
|
errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
5795
5843
|
})(errorUtil || (errorUtil = {}));
|
|
5796
5844
|
|
|
5797
|
-
// node_modules/zod/v3/types.js
|
|
5845
|
+
// ../../scalequality-ai-governance-service/node_modules/zod/v3/types.js
|
|
5798
5846
|
var ParseInputLazyPath = class {
|
|
5799
5847
|
constructor(parent, value, path, key) {
|
|
5800
5848
|
this._cachedPath = [];
|
|
@@ -9640,7 +9688,8 @@ var SdkEventMapper = class {
|
|
|
9640
9688
|
startedAt: iso(startedAt)
|
|
9641
9689
|
} });
|
|
9642
9690
|
const target = activityTarget(name, input);
|
|
9643
|
-
|
|
9691
|
+
const description = d.code === "STEP_COMMAND_DESCRIBED" && typeof d.params?.description === "string" ? d.params.description : void 0;
|
|
9692
|
+
this.cb.emit({ type: "activity", data: { tool: name, ...target ? { target } : {}, ...description ? { description } : {} } });
|
|
9644
9693
|
}
|
|
9645
9694
|
stepDone(id, t, status, endedAt = this.now()) {
|
|
9646
9695
|
this.cb.emit({ type: "step", data: {
|
|
@@ -9851,7 +9900,8 @@ function activityTarget(name, input) {
|
|
|
9851
9900
|
for (const part of s("command").split(/&&|\|\||[;|\n]/)) {
|
|
9852
9901
|
for (const token of part.trim().split(/\s+/)) {
|
|
9853
9902
|
if (!token || token.includes("=") || COMMAND_WRAPPERS.has(token)) continue;
|
|
9854
|
-
if (
|
|
9903
|
+
if (SHELL_PREFIX.has(token)) continue;
|
|
9904
|
+
if (COMMAND_SETUP.has(token) || SHELL_HEADER.has(token)) break;
|
|
9855
9905
|
if (!/^[A-Za-z0-9._/-]+$/.test(token)) return void 0;
|
|
9856
9906
|
const word = token.split("/").filter(Boolean).pop() ?? "";
|
|
9857
9907
|
return word && word.length <= 40 ? word : void 0;
|
|
@@ -9862,6 +9912,8 @@ function activityTarget(name, input) {
|
|
|
9862
9912
|
}
|
|
9863
9913
|
var COMMAND_WRAPPERS = /* @__PURE__ */ new Set(["sudo", "env", "time", "nice", "exec", "command", "nohup"]);
|
|
9864
9914
|
var COMMAND_SETUP = /* @__PURE__ */ new Set(["cd", "pushd", "popd", "export", "source", ".", "set", "unset"]);
|
|
9915
|
+
var SHELL_HEADER = /* @__PURE__ */ new Set(["for", "case", "select", "[", "[[", "test", "true", "false", ":"]);
|
|
9916
|
+
var SHELL_PREFIX = /* @__PURE__ */ new Set(["do", "then", "else", "elif", "if", "while", "until", "done", "fi", "esac", "!", "{", "}", "(", ")"]);
|
|
9865
9917
|
function blockText(content) {
|
|
9866
9918
|
if (typeof content === "string") return content;
|
|
9867
9919
|
if (Array.isArray(content)) {
|
|
@@ -10863,6 +10915,8 @@ var WorkspaceEngine = class {
|
|
|
10863
10915
|
thinkingTotals = /* @__PURE__ */ new Map();
|
|
10864
10916
|
/** The imported history, fetched once when a turn needs it. */
|
|
10865
10917
|
importedContext = null;
|
|
10918
|
+
/** The earlier part of this conversation (sessions before this one), fetched once when a turn needs it. */
|
|
10919
|
+
earlierContext = null;
|
|
10866
10920
|
/** What the running turn ended with, for SQ Auto's next choice: its last command's exit code and whether it failed. */
|
|
10867
10921
|
turnWatch = null;
|
|
10868
10922
|
/** Why the previous turn ended in trouble (null when it did not): SQ Auto takes the hard-task model for the next one. */
|
|
@@ -11753,6 +11807,19 @@ ${String(item.content)}` : String(item.content);
|
|
|
11753
11807
|
this.deps.log.warn("credential renewal failed", { error: this.redactor.text(e.message) });
|
|
11754
11808
|
}
|
|
11755
11809
|
}
|
|
11810
|
+
/**
|
|
11811
|
+
* The organization's protections in force now, at the start of each turn: a change on the AI protection page
|
|
11812
|
+
* (tool approval turned off, a rule turned on) holds from the next message, without a new credential. A failure
|
|
11813
|
+
* (an older API, no answer) keeps the ones this engine has.
|
|
11814
|
+
*/
|
|
11815
|
+
async refreshProtections() {
|
|
11816
|
+
if (!this.deps.transport.protections || !this.boot?.runtime) return;
|
|
11817
|
+
try {
|
|
11818
|
+
this.boot.runtime.protections = await this.deps.transport.protections();
|
|
11819
|
+
} catch (e) {
|
|
11820
|
+
this.deps.log.warn("protections not refreshed", { error: this.redactor.text(e.message) });
|
|
11821
|
+
}
|
|
11822
|
+
}
|
|
11756
11823
|
/**
|
|
11757
11824
|
* STREAM_BUFFERED, once per reason: answers on this alias are shown only after the AI protection inspects them
|
|
11758
11825
|
* (the organization's output rules, a semantic inspector, the application's own rules) or come whole from the
|
|
@@ -12169,6 +12236,7 @@ ${json}
|
|
|
12169
12236
|
const switching = typeof payload.model === "string" && !!payload.model && payload.model !== this.boot.model;
|
|
12170
12237
|
if (switching) await this.switchModel(payload.model);
|
|
12171
12238
|
else if (this.refreshCredential) await this.renewCredential();
|
|
12239
|
+
else await this.refreshProtections();
|
|
12172
12240
|
this.refreshCredential = false;
|
|
12173
12241
|
const boot = this.boot;
|
|
12174
12242
|
const sdk = this.sdk;
|
|
@@ -12224,7 +12292,7 @@ ${context.blocks.join("\n\n")}`);
|
|
|
12224
12292
|
const forkAt = canResume ? this.resumeAt : null;
|
|
12225
12293
|
this.resumeAt = null;
|
|
12226
12294
|
const withImported = async (text3) => {
|
|
12227
|
-
const block = await this.importedHistoryBlock();
|
|
12295
|
+
const block = [await this.earlierHistoryBlock(), await this.importedHistoryBlock()].filter(Boolean).join("\n\n");
|
|
12228
12296
|
return !block ? text3 : slash ? `${text3}
|
|
12229
12297
|
|
|
12230
12298
|
${block}` : `${block}
|
|
@@ -12699,6 +12767,18 @@ ${text3}`;
|
|
|
12699
12767
|
}
|
|
12700
12768
|
}).finally(() => w.abort.abort());
|
|
12701
12769
|
}
|
|
12770
|
+
/** The earlier sessions of this conversation as a context block (fetched once); null when there is none or it cannot be read. */
|
|
12771
|
+
earlierHistoryBlock() {
|
|
12772
|
+
if (!this.deps.transport.earlierConversation) return Promise.resolve(null);
|
|
12773
|
+
if (!this.earlierContext) {
|
|
12774
|
+
this.earlierContext = this.deps.transport.earlierConversation().then((sessions) => buildEarlierContext(sessions)).catch((e) => {
|
|
12775
|
+
this.deps.log.warn("earlier conversation unavailable", { error: this.redactor.text(e.message) });
|
|
12776
|
+
this.earlierContext = null;
|
|
12777
|
+
return null;
|
|
12778
|
+
});
|
|
12779
|
+
}
|
|
12780
|
+
return this.earlierContext;
|
|
12781
|
+
}
|
|
12702
12782
|
/** The imported conversation as a context block (fetched once); null when there is none or it cannot be read. */
|
|
12703
12783
|
importedHistoryBlock() {
|
|
12704
12784
|
const info = this.boot?.imported;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scalequality/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
4
4
|
"description": "ScaleQuality CLI. Connect your computer to the ScaleQuality AI Workspace (`scalequality login`), run its coding engine in any folder of your computer, and import your Claude Code and Codex conversations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|