@qwen-code/qwen-code 0.18.0 → 0.18.1-nightly.20260616.a68b2e1e7
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/bundled/loop/SKILL.md +2 -1
- package/bundled/qc-helper/docs/common-workflow.md +4 -4
- package/bundled/qc-helper/docs/configuration/auth.md +1 -1
- package/bundled/qc-helper/docs/configuration/model-providers.md +13 -6
- package/bundled/qc-helper/docs/configuration/settings.md +90 -87
- package/bundled/qc-helper/docs/features/dual-output.md +37 -3
- package/bundled/qc-helper/docs/features/skills.md +29 -3
- package/bundled/qc-helper/docs/features/sub-agents.md +2 -1
- package/bundled/qc-helper/docs/qwen-serve.md +32 -23
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +30 -30
- package/chunks/{agent-LOTJK6AH.js → agent-PXMT2XR5.js} +21 -20
- package/chunks/{agent-headless-TU3EPMYU.js → agent-headless-SY7VJUHV.js} +21 -20
- package/chunks/{anthropicContentGenerator-2HBRNQ3B.js → anthropicContentGenerator-DCI26OQF.js} +4 -4
- package/chunks/{askUserQuestion-OGCMIBQM.js → askUserQuestion-NDNFGC35.js} +2 -2
- package/chunks/{ca-BARBRL6N.js → ca-RK4QPLIX.js} +18 -1
- package/chunks/{chunk-BIVG75CP.js → chunk-26QELEL2.js} +1 -1
- package/chunks/{chunk-ZTZ4DDQE.js → chunk-3NRO6NHX.js} +2 -2
- package/chunks/{chunk-XV4HCEVI.js → chunk-6WPY6ES3.js} +41 -22
- package/chunks/{chunk-6YIUGZTC.js → chunk-A3OEZT2F.js} +281 -132
- package/chunks/{chunk-LBP46COL.js → chunk-ABRZC6FA.js} +83 -15
- package/chunks/{chunk-A7B4ISQP.js → chunk-B4ZF2KSI.js} +1 -1
- package/chunks/chunk-BJ5HQ23U.js +178 -0
- package/chunks/{chunk-OHEGWO4L.js → chunk-CPVI5J2L.js} +1 -1
- package/chunks/{chunk-SEGYWKIH.js → chunk-FIQECJTQ.js} +1 -1
- package/chunks/{chunk-IWAYOW5Q.js → chunk-H4ZDM3N6.js} +6588 -4196
- package/chunks/{chunk-HR7SV7AY.js → chunk-HA2UEYZP.js} +6 -2
- package/chunks/{chunk-2Y5SYSD3.js → chunk-IDYDPBBN.js} +3 -3
- package/chunks/{chunk-3HTIVKZE.js → chunk-IQHSD7K5.js} +1 -1
- package/chunks/{chunk-MFBBBTNY.js → chunk-JZFEL3RB.js} +1 -1
- package/chunks/{chunk-B7HXHOHU.js → chunk-LXYWINWF.js} +1 -1
- package/chunks/{chunk-IDX6COTE.js → chunk-LYRSMKLS.js} +2 -2
- package/chunks/{chunk-M6VTDSVR.js → chunk-LYSND7KR.js} +9 -4
- package/chunks/{chunk-7BCMOPIM.js → chunk-M5PJ5QAF.js} +31 -12
- package/chunks/{chunk-EYENRK4D.js → chunk-NNIYWQIS.js} +1 -1
- package/chunks/chunk-OMX7CUOE.js +356 -0
- package/chunks/{chunk-R7ODSGTK.js → chunk-OT6JA3KQ.js} +2 -2
- package/chunks/{chunk-72LDN5PP.js → chunk-QP4R5FTG.js} +1 -1
- package/chunks/{chunk-3DHXZ6EV.js → chunk-SFRV6BGY.js} +6 -4
- package/chunks/{chunk-LEJ42GNY.js → chunk-TSBXGR73.js} +6 -6
- package/chunks/{chunk-PL3MVCWD.js → chunk-UOB6KPGG.js} +11 -11
- package/chunks/{chunk-JTQAQBTV.js → chunk-VU6A2OBJ.js} +20 -6
- package/chunks/{chunk-HLPLOD42.js → chunk-VXHYMZXW.js} +1 -1
- package/chunks/{chunk-J5MDQKJL.js → chunk-WPTCDQN6.js} +2 -347
- package/chunks/{chunk-SNGELLWX.js → chunk-ZMIBJS45.js} +1 -1
- package/chunks/{chunk-XBY7E2FX.js → chunk-ZOFNJQNJ.js} +6 -4
- package/chunks/computer-use-7SEQDSHB.js +2052 -0
- package/chunks/{contextCommand-K347QT6O.js → contextCommand-KM5OWV65.js} +23 -22
- package/chunks/cron-create-7CXEAJ2K.js +184 -0
- package/chunks/{cron-delete-WKWSJZQA.js → cron-delete-2FQYYNQ6.js} +27 -4
- package/chunks/{cron-list-B52XEXAZ.js → cron-list-QCAJ73XE.js} +39 -6
- package/chunks/{de-YGKK2BC4.js → de-FGPM4KW5.js} +18 -1
- package/chunks/{dist-4LXD6L6X.js → dist-2UCAYOX7.js} +2 -2
- package/chunks/{dist-H6ONXVLG.js → dist-33LHH26D.js} +1 -1
- package/chunks/{dist-PK7DFCAW.js → dist-KF43SZZV.js} +1 -1
- package/chunks/{dist-KAZ3SEBX.js → dist-PF2IYSMD.js} +1 -1
- package/chunks/{edit-KU4PJGEX.js → edit-BMUKPLA7.js} +23 -24
- package/chunks/{en-DHGYHIHX.js → en-VP6XPGEC.js} +5 -2
- package/chunks/{enter-worktree-PPYIDCWI.js → enter-worktree-LXJ5WJ5A.js} +21 -20
- package/chunks/{enterPlanMode-5CZDMCB4.js → enterPlanMode-QWRZ54ZF.js} +21 -20
- package/chunks/{exit-worktree-UY3CGHKC.js → exit-worktree-5HTQPNZO.js} +21 -20
- package/chunks/{exitPlanMode-3DN4QNSG.js → exitPlanMode-5WQAXNDA.js} +71 -31
- package/chunks/{fr-JXBKPJKQ.js → fr-ATYBVCLT.js} +18 -1
- package/chunks/{geminiContentGenerator-7A6I2RWB.js → geminiContentGenerator-CAKHT5YE.js} +4 -4
- package/chunks/{glob-OFNQSS52.js → glob-5DN6NSCD.js} +21 -20
- package/chunks/{grep-6J2MSUM5.js → grep-BJILOLCD.js} +30 -26
- package/chunks/{ja-TGPZSP2B.js → ja-W2QEA2OI.js} +18 -1
- package/chunks/{keychain-token-storage-6IU6ORQN.js → keychain-token-storage-QSTRHKKL.js} +2 -2
- package/chunks/{ls-V3O6A5PT.js → ls-XVGXRYWD.js} +3 -3
- package/chunks/{lsp-G2OCIFUA.js → lsp-S6SHPULC.js} +2 -2
- package/chunks/{monitor-FKLHV423.js → monitor-SUEMSRN3.js} +21 -20
- package/chunks/{notebook-edit-KTBYFKWG.js → notebook-edit-6F6Z5P6U.js} +22 -21
- package/chunks/{openaiContentGenerator-L5KSWQY7.js → openaiContentGenerator-DO27LL6O.js} +11 -11
- package/chunks/{pt-TIBG6BIO.js → pt-ZKEWJFBW.js} +18 -1
- package/chunks/{qwenContentGenerator-PYOXLMBW.js → qwenContentGenerator-DQLGLQSH.js} +23 -22
- package/chunks/{qwenOAuth2-2KCKWDCF.js → qwenOAuth2-KK433U33.js} +4 -4
- package/chunks/{read-file-JQVRK4NU.js → read-file-3TBLYTOQ.js} +8 -8
- package/chunks/{ripGrep-2L4LPNAJ.js → ripGrep-3INYT3QV.js} +21 -20
- package/chunks/{ru-JBCHCK4L.js → ru-VEKTPJ74.js} +18 -1
- package/chunks/{scheduler-FGNXY4JQ.js → scheduler-23KQW6CX.js} +21 -20
- package/chunks/{send-message-SZFWNOCL.js → send-message-SMNR5DBG.js} +2 -2
- package/chunks/{serve-N2IBLA3G.js → serve-Y5E4LKUI.js} +998 -278
- package/chunks/{shell-PTEG6UX4.js → shell-4H6XQXVY.js} +21 -20
- package/chunks/{skill-X4NTK4NH.js → skill-SE6FECZR.js} +10 -10
- package/chunks/{src-GLLQ3R5W.js → src-76DUBH3A.js} +42 -26
- package/chunks/{syntheticOutput-IKAY5F6X.js → syntheticOutput-KMNF7YG6.js} +3 -3
- package/chunks/{task-create-MQICOJFV.js → task-create-LIJHK75G.js} +7 -6
- package/chunks/{task-list-RIHJCH32.js → task-list-S4GNSILM.js} +6 -5
- package/chunks/{task-stop-FWZRFANS.js → task-stop-3GBRYJHM.js} +2 -2
- package/chunks/{task-update-2LHPXOYM.js → task-update-F3UTVJMS.js} +7 -6
- package/chunks/{team-create-2E4PF4KN.js → team-create-Q5DTDDH4.js} +21 -20
- package/chunks/{team-delete-DAUDQS4J.js → team-delete-54434EB7.js} +6 -5
- package/chunks/{todoWrite-HTUACZES.js → todoWrite-4ENGSBUX.js} +4 -4
- package/chunks/{tool-search-KTVULRES.js → tool-search-ABZMSDTU.js} +8 -8
- package/chunks/{web-fetch-CZ7LLKPE.js → web-fetch-RHZMF3MP.js} +4 -4
- package/chunks/{workflow-L2ZUUDT2.js → workflow-NEMDQB75.js} +503 -49
- package/chunks/{write-file-ZEB2JDYH.js → write-file-VAEHZPSL.js} +22 -21
- package/chunks/{zh-7H5OQC4I.js → zh-OIXDDQHB.js} +5 -2
- package/chunks/{zh-TW-P4IDHD3M.js → zh-TW-6YFNCKTA.js} +5 -2
- package/cli-entry.js +19 -0
- package/cli.js +6643 -4971
- package/locales/ca.js +20 -2
- package/locales/de.js +21 -2
- package/locales/en.js +7 -4
- package/locales/fr.js +22 -2
- package/locales/ja.js +22 -2
- package/locales/pt.js +21 -2
- package/locales/ru.js +20 -2
- package/locales/zh-TW.js +6 -4
- package/locales/zh.js +6 -4
- package/package.json +4 -3
- package/chunks/chunk-SKBPNJEW.js +0 -45
- package/chunks/computer-use-3RH2DOM6.js +0 -825
- package/chunks/cron-create-YJL3KFWI.js +0 -140
|
@@ -6,31 +6,32 @@ import {
|
|
|
6
6
|
getLanguageSettingsOptions,
|
|
7
7
|
t,
|
|
8
8
|
writeStderrLine
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UOB6KPGG.js";
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_STOP_HOOK_BLOCK_CAP,
|
|
12
12
|
DEFAULT_TOOL_OUTPUT_BATCH_BUDGET,
|
|
13
|
+
DEFAULT_TOOL_RESULTS_TOTAL_CHARS_THRESHOLD,
|
|
13
14
|
DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES,
|
|
14
15
|
DEFAULT_TRUNCATE_TOOL_OUTPUT_THRESHOLD,
|
|
15
16
|
IdeClient,
|
|
16
17
|
SkillError,
|
|
17
18
|
ideContextStore,
|
|
18
19
|
require_main
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-H4ZDM3N6.js";
|
|
20
21
|
import {
|
|
21
22
|
isWithinRoot,
|
|
22
23
|
stripRuntimeSnapshotPrefix
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-A3OEZT2F.js";
|
|
24
25
|
import {
|
|
25
26
|
atomicWriteFileSync
|
|
26
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-LXYWINWF.js";
|
|
27
28
|
import {
|
|
28
29
|
FatalConfigError,
|
|
29
30
|
QWEN_DIR,
|
|
30
31
|
Storage,
|
|
31
32
|
createDebugLogger,
|
|
32
33
|
getErrorMessage
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-HA2UEYZP.js";
|
|
34
35
|
import {
|
|
35
36
|
init_esbuild_shims
|
|
36
37
|
} from "./chunk-A4BMJM77.js";
|
|
@@ -13562,6 +13563,23 @@ var SessionLimitExceededError = class extends Error {
|
|
|
13562
13563
|
this.limit = limit;
|
|
13563
13564
|
}
|
|
13564
13565
|
};
|
|
13566
|
+
var PromptQueueFullError = class extends Error {
|
|
13567
|
+
static {
|
|
13568
|
+
__name(this, "PromptQueueFullError");
|
|
13569
|
+
}
|
|
13570
|
+
limit;
|
|
13571
|
+
pendingCount;
|
|
13572
|
+
sessionId;
|
|
13573
|
+
constructor(limit, pendingCount, sessionId) {
|
|
13574
|
+
super(
|
|
13575
|
+
`Prompt queue full for session "${sessionId}" (${pendingCount}/${limit} pending)`
|
|
13576
|
+
);
|
|
13577
|
+
this.name = "PromptQueueFullError";
|
|
13578
|
+
this.limit = limit;
|
|
13579
|
+
this.pendingCount = pendingCount;
|
|
13580
|
+
this.sessionId = sessionId;
|
|
13581
|
+
}
|
|
13582
|
+
};
|
|
13565
13583
|
var WorkspaceMismatchError = class extends Error {
|
|
13566
13584
|
static {
|
|
13567
13585
|
__name(this, "WorkspaceMismatchError");
|
|
@@ -13591,6 +13609,24 @@ var InvalidClientIdError = class extends Error {
|
|
|
13591
13609
|
this.clientId = clientId;
|
|
13592
13610
|
}
|
|
13593
13611
|
};
|
|
13612
|
+
var SessionShellDisabledError = class extends Error {
|
|
13613
|
+
static {
|
|
13614
|
+
__name(this, "SessionShellDisabledError");
|
|
13615
|
+
}
|
|
13616
|
+
constructor() {
|
|
13617
|
+
super("Direct session shell is disabled for this daemon");
|
|
13618
|
+
this.name = "SessionShellDisabledError";
|
|
13619
|
+
}
|
|
13620
|
+
};
|
|
13621
|
+
var SessionShellClientRequiredError = class extends Error {
|
|
13622
|
+
static {
|
|
13623
|
+
__name(this, "SessionShellClientRequiredError");
|
|
13624
|
+
}
|
|
13625
|
+
constructor() {
|
|
13626
|
+
super("Direct session shell requires a session-bound client id");
|
|
13627
|
+
this.name = "SessionShellClientRequiredError";
|
|
13628
|
+
}
|
|
13629
|
+
};
|
|
13594
13630
|
var InvalidPermissionOptionError = class extends Error {
|
|
13595
13631
|
static {
|
|
13596
13632
|
__name(this, "InvalidPermissionOptionError");
|
|
@@ -13774,9 +13810,7 @@ var BranchWhilePromptActiveError = class extends Error {
|
|
|
13774
13810
|
}
|
|
13775
13811
|
sessionId;
|
|
13776
13812
|
constructor(sessionId) {
|
|
13777
|
-
super(
|
|
13778
|
-
`Cannot branch session ${sessionId}: a prompt is currently active`
|
|
13779
|
-
);
|
|
13813
|
+
super(`Cannot branch session ${sessionId}: a prompt is currently active`);
|
|
13780
13814
|
this.name = "BranchWhilePromptActiveError";
|
|
13781
13815
|
this.sessionId = sessionId;
|
|
13782
13816
|
}
|
|
@@ -16373,7 +16407,7 @@ var SETTINGS_SCHEMA = {
|
|
|
16373
16407
|
category: "Context",
|
|
16374
16408
|
requiresRestart: false,
|
|
16375
16409
|
default: {},
|
|
16376
|
-
description: "Settings for clearing stale
|
|
16410
|
+
description: "Settings for clearing stale or oversized tool result context. Use -1 to disable a threshold.",
|
|
16377
16411
|
showInDialog: false,
|
|
16378
16412
|
properties: {
|
|
16379
16413
|
toolResultsThresholdMinutes: {
|
|
@@ -16393,6 +16427,15 @@ var SETTINGS_SCHEMA = {
|
|
|
16393
16427
|
default: 5,
|
|
16394
16428
|
description: "Number of most-recent compactable tool results to preserve when clearing. Floor at 1.",
|
|
16395
16429
|
showInDialog: false
|
|
16430
|
+
},
|
|
16431
|
+
toolResultsTotalCharsThreshold: {
|
|
16432
|
+
type: "number",
|
|
16433
|
+
label: "Tool Results Total Chars Threshold",
|
|
16434
|
+
category: "Context",
|
|
16435
|
+
requiresRestart: false,
|
|
16436
|
+
default: DEFAULT_TOOL_RESULTS_TOTAL_CHARS_THRESHOLD,
|
|
16437
|
+
description: "Total compactable tool result output characters allowed in history before clearing oldest results. Use -1 to disable. This is a soft threshold: protected recent tool results may keep the total above it.",
|
|
16438
|
+
showInDialog: false
|
|
16396
16439
|
}
|
|
16397
16440
|
}
|
|
16398
16441
|
},
|
|
@@ -16917,7 +16960,7 @@ var SETTINGS_SCHEMA = {
|
|
|
16917
16960
|
category: "Tools",
|
|
16918
16961
|
requiresRestart: true,
|
|
16919
16962
|
default: {},
|
|
16920
|
-
description: "Cross-platform desktop automation via the
|
|
16963
|
+
description: "Cross-platform desktop automation via the cua-driver native driver (trycua/cua). On first invocation a pinned, signed + notarized binary (~20MB) is downloaded into ~/.qwen/computer-use/ and the user is walked through macOS Accessibility / Screen Recording permissions if needed. Exposes cua-driver's full tool surface (click, type_text, scroll, drag, press_key, get_window_state, page, launch_app, and more).",
|
|
16921
16964
|
showInDialog: false,
|
|
16922
16965
|
properties: {
|
|
16923
16966
|
enabled: {
|
|
@@ -16926,8 +16969,17 @@ var SETTINGS_SCHEMA = {
|
|
|
16926
16969
|
category: "Tools",
|
|
16927
16970
|
requiresRestart: true,
|
|
16928
16971
|
default: true,
|
|
16929
|
-
description: "When enabled (default), the
|
|
16972
|
+
description: "When enabled (default), the cua-driver computer_use__* tools are registered as deferred built-ins.",
|
|
16930
16973
|
showInDialog: true
|
|
16974
|
+
},
|
|
16975
|
+
maxImageDimension: {
|
|
16976
|
+
type: "number",
|
|
16977
|
+
label: "Max Screenshot Dimension",
|
|
16978
|
+
category: "Tools",
|
|
16979
|
+
requiresRestart: true,
|
|
16980
|
+
default: -1,
|
|
16981
|
+
description: "Longest-edge pixel cap applied to cua-driver screenshots (via set_config's max_image_dimension). -1 (default) keeps cua-driver's built-in default (1568); 0 disables resizing (full resolution); a positive value caps the longest edge. Lower caps cut vision-token cost at the expense of fine detail. Overridable via the QWEN_COMPUTER_USE_MAX_IMAGE_DIMENSION env var.",
|
|
16982
|
+
showInDialog: false
|
|
16931
16983
|
}
|
|
16932
16984
|
}
|
|
16933
16985
|
}
|
|
@@ -18757,6 +18809,7 @@ var ENV_WAS_RECOVERED = "QWEN_CODE_SETTINGS_WAS_RECOVERED";
|
|
|
18757
18809
|
var PROJECT_ENV_HARDCODED_EXCLUSIONS = [
|
|
18758
18810
|
"QWEN_HOME",
|
|
18759
18811
|
"QWEN_RUNTIME_DIR",
|
|
18812
|
+
"QWEN_CODE_MCP_APPROVALS_PATH",
|
|
18760
18813
|
ENV_CORRUPTED_PATH,
|
|
18761
18814
|
ENV_WAS_RECOVERED
|
|
18762
18815
|
];
|
|
@@ -18914,8 +18967,20 @@ function getSettingsWarnings(loadedSettings) {
|
|
|
18914
18967
|
return [...warningSet];
|
|
18915
18968
|
}
|
|
18916
18969
|
__name(getSettingsWarnings, "getSettingsWarnings");
|
|
18970
|
+
function tagMcpServerScope(settings, scope) {
|
|
18971
|
+
const servers = settings.mcpServers;
|
|
18972
|
+
if (!servers || Object.keys(servers).length === 0) {
|
|
18973
|
+
return settings;
|
|
18974
|
+
}
|
|
18975
|
+
const tagged = {};
|
|
18976
|
+
for (const [name, config] of Object.entries(servers)) {
|
|
18977
|
+
tagged[name] = { ...config, scope };
|
|
18978
|
+
}
|
|
18979
|
+
return { ...settings, mcpServers: tagged };
|
|
18980
|
+
}
|
|
18981
|
+
__name(tagMcpServerScope, "tagMcpServerScope");
|
|
18917
18982
|
function mergeSettings(system, systemDefaults, user, workspace, isTrusted) {
|
|
18918
|
-
const safeWorkspace = isTrusted ? workspace : {};
|
|
18983
|
+
const safeWorkspace = isTrusted ? tagMcpServerScope(workspace, "workspace") : {};
|
|
18919
18984
|
return customDeepMerge(
|
|
18920
18985
|
getMergeStrategyForPath,
|
|
18921
18986
|
{},
|
|
@@ -18923,7 +18988,7 @@ function mergeSettings(system, systemDefaults, user, workspace, isTrusted) {
|
|
|
18923
18988
|
systemDefaults,
|
|
18924
18989
|
user,
|
|
18925
18990
|
safeWorkspace,
|
|
18926
|
-
system
|
|
18991
|
+
tagMcpServerScope(system, "system")
|
|
18927
18992
|
);
|
|
18928
18993
|
}
|
|
18929
18994
|
__name(mergeSettings, "mergeSettings");
|
|
@@ -19901,7 +19966,7 @@ __name(getPackageJson, "getPackageJson");
|
|
|
19901
19966
|
// packages/cli/src/utils/version.ts
|
|
19902
19967
|
async function getCliVersion() {
|
|
19903
19968
|
const pkgJson = await getPackageJson();
|
|
19904
|
-
return "0.18.
|
|
19969
|
+
return "0.18.1-nightly.20260616.a68b2e1e7";
|
|
19905
19970
|
}
|
|
19906
19971
|
__name(getCliVersion, "getCliVersion");
|
|
19907
19972
|
|
|
@@ -20051,7 +20116,7 @@ import { execFile } from "node:child_process";
|
|
|
20051
20116
|
|
|
20052
20117
|
// packages/cli/src/generated/git-commit.ts
|
|
20053
20118
|
init_esbuild_shims();
|
|
20054
|
-
var GIT_COMMIT_INFO = "
|
|
20119
|
+
var GIT_COMMIT_INFO = "d1b122e3a";
|
|
20055
20120
|
|
|
20056
20121
|
// packages/cli/src/utils/systemInfo.ts
|
|
20057
20122
|
var debugLogger4 = createDebugLogger("STATUS");
|
|
@@ -20277,8 +20342,11 @@ export {
|
|
|
20277
20342
|
RestoreInProgressError,
|
|
20278
20343
|
InvalidSessionScopeError,
|
|
20279
20344
|
SessionLimitExceededError,
|
|
20345
|
+
PromptQueueFullError,
|
|
20280
20346
|
WorkspaceMismatchError,
|
|
20281
20347
|
InvalidClientIdError,
|
|
20348
|
+
SessionShellDisabledError,
|
|
20349
|
+
SessionShellClientRequiredError,
|
|
20282
20350
|
InvalidPermissionOptionError,
|
|
20283
20351
|
InvalidSessionMetadataError,
|
|
20284
20352
|
PermissionPolicyNotImplementedError,
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
Mutex
|
|
5
|
+
} from "./chunk-OMX7CUOE.js";
|
|
6
|
+
import {
|
|
7
|
+
atomicWriteJSON
|
|
8
|
+
} from "./chunk-LXYWINWF.js";
|
|
9
|
+
import {
|
|
10
|
+
Storage,
|
|
11
|
+
createDebugLogger,
|
|
12
|
+
getProjectHash
|
|
13
|
+
} from "./chunk-HA2UEYZP.js";
|
|
14
|
+
import {
|
|
15
|
+
init_esbuild_shims
|
|
16
|
+
} from "./chunk-A4BMJM77.js";
|
|
17
|
+
import {
|
|
18
|
+
__name
|
|
19
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
20
|
+
|
|
21
|
+
// packages/core/src/services/cronTasksFile.ts
|
|
22
|
+
init_esbuild_shims();
|
|
23
|
+
import * as fs from "node:fs/promises";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
var debugLogger = createDebugLogger("CRON_TASKS_FILE");
|
|
26
|
+
var TASKS_FILENAME = "scheduled_tasks.json";
|
|
27
|
+
var CRON_TASKS_DISPLAY_PATH = `~/.qwen/tmp/<project-hash>/${TASKS_FILENAME}`;
|
|
28
|
+
var UPDATE_LOCK_RETRY_MS = 15;
|
|
29
|
+
var UPDATE_LOCK_STALE_MS = 2e3;
|
|
30
|
+
var UPDATE_LOCK_TIMEOUT_MS = 3e3;
|
|
31
|
+
var updateStaleSeq = 0;
|
|
32
|
+
var updateMutexes = /* @__PURE__ */ new Map();
|
|
33
|
+
function getUpdateMutex(filePath) {
|
|
34
|
+
let mutex = updateMutexes.get(filePath);
|
|
35
|
+
if (!mutex) {
|
|
36
|
+
mutex = new Mutex();
|
|
37
|
+
updateMutexes.set(filePath, mutex);
|
|
38
|
+
}
|
|
39
|
+
return mutex;
|
|
40
|
+
}
|
|
41
|
+
__name(getUpdateMutex, "getUpdateMutex");
|
|
42
|
+
function getCronFilePath(projectRoot) {
|
|
43
|
+
return path.join(
|
|
44
|
+
Storage.getGlobalTempDir(),
|
|
45
|
+
getProjectHash(projectRoot),
|
|
46
|
+
TASKS_FILENAME
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
__name(getCronFilePath, "getCronFilePath");
|
|
50
|
+
async function readCronTasks(projectRoot) {
|
|
51
|
+
const filePath = getCronFilePath(projectRoot);
|
|
52
|
+
let raw;
|
|
53
|
+
try {
|
|
54
|
+
raw = await fs.readFile(filePath, "utf-8");
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err.code === "ENOENT") return [];
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(raw);
|
|
62
|
+
} catch {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Malformed JSON in ${filePath} \u2014 fix or delete the file; refusing to treat it as an empty schedule.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (!Array.isArray(parsed)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Expected a JSON array in ${filePath} \u2014 fix or delete the file; refusing to treat it as an empty schedule.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
const valid = parsed.filter(isValidTask);
|
|
73
|
+
if (valid.length !== parsed.length) {
|
|
74
|
+
debugLogger.warn(
|
|
75
|
+
`Dropped ${parsed.length - valid.length} invalid task entr${parsed.length - valid.length === 1 ? "y" : "ies"} from ${filePath}; a later write will persist without ${parsed.length - valid.length === 1 ? "it" : "them"}.`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return valid;
|
|
79
|
+
}
|
|
80
|
+
__name(readCronTasks, "readCronTasks");
|
|
81
|
+
async function writeCronTasks(projectRoot, tasks) {
|
|
82
|
+
const filePath = getCronFilePath(projectRoot);
|
|
83
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
84
|
+
await atomicWriteJSON(filePath, tasks, { noFollow: true });
|
|
85
|
+
}
|
|
86
|
+
__name(writeCronTasks, "writeCronTasks");
|
|
87
|
+
async function acquireUpdateLock(filePath) {
|
|
88
|
+
const lockPath = `${filePath}.lock`;
|
|
89
|
+
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
90
|
+
const deadline = Date.now() + UPDATE_LOCK_TIMEOUT_MS;
|
|
91
|
+
for (; ; ) {
|
|
92
|
+
if (Date.now() > deadline) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Timed out waiting for scheduled-tasks lock (${lockPath})`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
await fs.writeFile(lockPath, String(process.pid), { flag: "wx" });
|
|
99
|
+
return async () => {
|
|
100
|
+
await fs.unlink(lockPath).catch(() => {
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
} catch (err) {
|
|
104
|
+
if (err.code !== "EEXIST") throw err;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const stat2 = await fs.stat(lockPath);
|
|
108
|
+
if (Date.now() - stat2.mtimeMs > UPDATE_LOCK_STALE_MS) {
|
|
109
|
+
const stalePath = `${lockPath}.stale.${process.pid}.${updateStaleSeq++}`;
|
|
110
|
+
try {
|
|
111
|
+
await fs.rename(lockPath, stalePath);
|
|
112
|
+
} catch {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const moved = await fs.stat(stalePath).catch(() => null);
|
|
116
|
+
if (moved && Date.now() - moved.mtimeMs <= UPDATE_LOCK_STALE_MS) {
|
|
117
|
+
await fs.link(stalePath, lockPath).catch(() => {
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
await fs.unlink(stalePath).catch(() => {
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
await new Promise((resolve) => setTimeout(resolve, UPDATE_LOCK_RETRY_MS));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
__name(acquireUpdateLock, "acquireUpdateLock");
|
|
131
|
+
async function updateCronTasks(projectRoot, mutate) {
|
|
132
|
+
const filePath = getCronFilePath(projectRoot);
|
|
133
|
+
return getUpdateMutex(filePath).runExclusive(async () => {
|
|
134
|
+
const release = await acquireUpdateLock(filePath);
|
|
135
|
+
try {
|
|
136
|
+
const tasks = await readCronTasks(projectRoot);
|
|
137
|
+
const next = mutate(tasks);
|
|
138
|
+
if (next !== tasks) {
|
|
139
|
+
await writeCronTasks(projectRoot, next);
|
|
140
|
+
}
|
|
141
|
+
} finally {
|
|
142
|
+
await release();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
__name(updateCronTasks, "updateCronTasks");
|
|
147
|
+
async function addCronTask(projectRoot, task) {
|
|
148
|
+
await updateCronTasks(projectRoot, (tasks) => [...tasks, task]);
|
|
149
|
+
}
|
|
150
|
+
__name(addCronTask, "addCronTask");
|
|
151
|
+
async function removeCronTasks(projectRoot, ids) {
|
|
152
|
+
const idSet = new Set(ids);
|
|
153
|
+
const current = await readCronTasks(projectRoot);
|
|
154
|
+
if (!current.some((t) => idSet.has(t.id))) return 0;
|
|
155
|
+
let removed = 0;
|
|
156
|
+
await updateCronTasks(projectRoot, (tasks) => {
|
|
157
|
+
const remaining = tasks.filter((t) => !idSet.has(t.id));
|
|
158
|
+
removed = tasks.length - remaining.length;
|
|
159
|
+
return removed === 0 ? tasks : remaining;
|
|
160
|
+
});
|
|
161
|
+
return removed;
|
|
162
|
+
}
|
|
163
|
+
__name(removeCronTasks, "removeCronTasks");
|
|
164
|
+
function isValidTask(value) {
|
|
165
|
+
if (typeof value !== "object" || value === null) return false;
|
|
166
|
+
const obj = value;
|
|
167
|
+
return typeof obj["id"] === "string" && typeof obj["cron"] === "string" && typeof obj["prompt"] === "string" && typeof obj["recurring"] === "boolean" && typeof obj["createdAt"] === "number" && (obj["lastFiredAt"] === null || typeof obj["lastFiredAt"] === "number");
|
|
168
|
+
}
|
|
169
|
+
__name(isValidTask, "isValidTask");
|
|
170
|
+
|
|
171
|
+
export {
|
|
172
|
+
CRON_TASKS_DISPLAY_PATH,
|
|
173
|
+
getCronFilePath,
|
|
174
|
+
readCronTasks,
|
|
175
|
+
updateCronTasks,
|
|
176
|
+
addCronTask,
|
|
177
|
+
removeCronTasks
|
|
178
|
+
};
|