cclawd 2026.3.37 → 2026.3.38
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/.buildstamp +1 -1
- package/dist/build-info.json +3 -3
- package/dist/extensions/cclawd-guard/index.js +18 -5
- package/dist/extensions/feishu/node_modules/.package-lock.json +3 -3
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/README.md +4 -0
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/README.zh.md +4 -0
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/es/index.js +33 -1
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/lib/index.js +33 -1
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/package.json +1 -1
- package/dist/extensions/feishu/node_modules/@larksuiteoapi/node-sdk/types/index.d.ts +19 -0
- package/package.json +1 -1
package/dist/.buildstamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"builtAt":
|
|
1
|
+
{"builtAt":1779847731292,"head":"130310d3504f3dbf6c85523f813ceef7e406e463"}
|
package/dist/build-info.json
CHANGED
|
@@ -561,17 +561,27 @@ var BehaviorDetector = class {
|
|
|
561
561
|
this.pendingQuotaMessage = null;
|
|
562
562
|
return msg;
|
|
563
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* Update current-turn user intent from a raw user message (message_received only).
|
|
566
|
+
* Do not call with agent prompts — they may include channel envelopes/system injection.
|
|
567
|
+
*/
|
|
564
568
|
setUserIntent(sessionKey, message) {
|
|
565
569
|
const state = this.getOrCreate(sessionKey);
|
|
566
|
-
|
|
567
|
-
const effectiveMessage = message.replace(REAL_PERSON_AUTH_BYPASS_MARKER, "").trim() || message;
|
|
568
|
-
if (hasBypassMarker) {
|
|
570
|
+
if (message.includes(REAL_PERSON_AUTH_BYPASS_MARKER)) {
|
|
569
571
|
state.realPersonAuthBypassOncePending = true;
|
|
570
572
|
this.log.info("Detected real-person-auth bypass marker; next tool call will be allowed once.");
|
|
571
573
|
}
|
|
572
|
-
|
|
574
|
+
const effectiveMessage = this.stripBypassMarker(message);
|
|
575
|
+
state.userIntent = effectiveMessage.slice(0, 500);
|
|
573
576
|
state.recentUserMessages = [...state.recentUserMessages.slice(-4), effectiveMessage.slice(0, 200)];
|
|
574
577
|
}
|
|
578
|
+
/** Detect real-person-auth one-shot bypass marker in the agent prompt (before_agent_start). */
|
|
579
|
+
handleAuthBypassMarker(sessionKey, message) {
|
|
580
|
+
if (!message.includes(REAL_PERSON_AUTH_BYPASS_MARKER)) return;
|
|
581
|
+
const state = this.getOrCreate(sessionKey);
|
|
582
|
+
state.realPersonAuthBypassOncePending = true;
|
|
583
|
+
this.log.info("Detected real-person-auth bypass marker; next tool call will be allowed once.");
|
|
584
|
+
}
|
|
575
585
|
clearSession(sessionKey) {
|
|
576
586
|
this.sessions.delete(sessionKey);
|
|
577
587
|
}
|
|
@@ -796,6 +806,9 @@ var BehaviorDetector = class {
|
|
|
796
806
|
clearTimeout(timer);
|
|
797
807
|
}
|
|
798
808
|
}
|
|
809
|
+
stripBypassMarker(message) {
|
|
810
|
+
return message.replace(REAL_PERSON_AUTH_BYPASS_MARKER, "").trim() || message;
|
|
811
|
+
}
|
|
799
812
|
detectLocalHardBlock(userIntent, toolName, params) {
|
|
800
813
|
const paramsText = JSON.stringify(params ?? {}).toLowerCase();
|
|
801
814
|
const context = [
|
|
@@ -1875,7 +1888,7 @@ const openClawGuardPlugin = {
|
|
|
1875
1888
|
const text = typeof event.prompt === "string" ? event.prompt : JSON.stringify(event.prompt ?? "");
|
|
1876
1889
|
const runId = `run-${randomBytes(8).toString("hex")}`;
|
|
1877
1890
|
globalEventReporter?.setRunId(sessionKey, runId);
|
|
1878
|
-
if (globalBehaviorDetector && event.prompt) globalBehaviorDetector.
|
|
1891
|
+
if (globalBehaviorDetector && event.prompt) globalBehaviorDetector.handleAuthBypassMarker(sessionKey, text);
|
|
1879
1892
|
globalEventReporter?.report(sessionKey, "before_agent_start", {
|
|
1880
1893
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1881
1894
|
prompt: text,
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"requires": true,
|
|
4
4
|
"packages": {
|
|
5
5
|
"node_modules/@larksuiteoapi/node-sdk": {
|
|
6
|
-
"version": "1.
|
|
7
|
-
"resolved": "https://registry.npmjs.org/@larksuiteoapi/node-sdk/-/node-sdk-1.
|
|
8
|
-
"integrity": "sha512-
|
|
6
|
+
"version": "1.66.0",
|
|
7
|
+
"resolved": "https://registry.npmjs.org/@larksuiteoapi/node-sdk/-/node-sdk-1.66.0.tgz",
|
|
8
|
+
"integrity": "sha512-ueKbbdvmVGVie3KvKbvHZqvDC/gg3M0rRDeyQanQWK+i2bQgiiTpIfpqVWvxuTgprV31yqV7HPMjN6KegWSCfA==",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"axios": "~1.13.3",
|
|
@@ -691,6 +691,10 @@ try {
|
|
|
691
691
|
| signal | `AbortSignal` to cancel the polling | AbortSignal | No | - |
|
|
692
692
|
| onQRCodeReady | Callback when the verification URL is ready. Receives `{ url, expireIn }`. You can render the URL as a QR code for users to scan, or display it as a link | function | Yes | - |
|
|
693
693
|
| onStatusChange | Callback on polling status changes. Receives `{ status, interval? }`. Status values: `polling`, `slow_down`, `domain_switched` | function | No | - |
|
|
694
|
+
| appPreset | Pre-fill values for the app-creation page. All fields are optional; users can still edit them on the page | AppPreset | No | - |
|
|
695
|
+
| appPreset.avatar | App avatar URL(s). 1-6 URLs supported; the first one is selected by default. Allowed formats: png / jpg / jpeg / webp / gif (gif is sampled to a single frame, not animated) | string \| string[] | No | - |
|
|
696
|
+
| appPreset.name | App name. Supports the `{user}` placeholder (replaced with the scanning user's name) | string | No | - |
|
|
697
|
+
| appPreset.desc | App description. Supports the `{user}` placeholder | string | No | - |
|
|
694
698
|
|
|
695
699
|
#### Return value
|
|
696
700
|
|
|
@@ -753,6 +753,10 @@ try {
|
|
|
753
753
|
| signal | 用于取消轮询的 `AbortSignal` | AbortSignal | 否 | - |
|
|
754
754
|
| onQRCodeReady | 验证链接就绪时的回调,参数为 `{ url, expireIn }`。可将 URL 渲染为二维码供用户扫码,或直接作为链接展示 | function | 是 | - |
|
|
755
755
|
| onStatusChange | 轮询状态变化时的回调,参数为 `{ status, interval? }`。status 取值:`polling`、`slow_down`、`domain_switched` | function | 否 | - |
|
|
756
|
+
| appPreset | 预设应用信息(头像、名称、描述)。所有字段都是可选的,用户扫码后仍可在页面手动修改 | AppPreset | 否 | - |
|
|
757
|
+
| appPreset.avatar | 应用头像 URL,支持 1-6 个;传多个时默认选中第一个。支持 png / jpg / jpeg / webp / gif(gif 自动取一帧,不保留动图) | string \| string[] | 否 | - |
|
|
758
|
+
| appPreset.name | 应用名称,支持 `{user}` 占位符(替换为扫码用户名称) | string | 否 | - |
|
|
759
|
+
| appPreset.desc | 应用描述,支持 `{user}` 占位符 | string | 否 | - |
|
|
756
760
|
|
|
757
761
|
#### 返回值
|
|
758
762
|
|
|
@@ -89750,6 +89750,35 @@ const SDK_NAME = 'node-sdk';
|
|
|
89750
89750
|
const DEFAULT_FEISHU_DOMAIN = 'accounts.feishu.cn';
|
|
89751
89751
|
const DEFAULT_LARK_DOMAIN = 'accounts.larksuite.com';
|
|
89752
89752
|
const ENDPOINT = '/oauth/v1/app/registration';
|
|
89753
|
+
const AVATAR_MAX_COUNT = 6;
|
|
89754
|
+
/**
|
|
89755
|
+
* Append `avatar` / `name` / `desc` query params to the QR code URL.
|
|
89756
|
+
* `URLSearchParams` handles URL encoding automatically.
|
|
89757
|
+
*/
|
|
89758
|
+
function applyAppPreset(qrCodeUrl, preset) {
|
|
89759
|
+
const { avatar, name, desc } = preset;
|
|
89760
|
+
if (avatar !== undefined) {
|
|
89761
|
+
const avatars = Array.isArray(avatar) ? avatar : [avatar];
|
|
89762
|
+
if (avatars.length === 0) {
|
|
89763
|
+
throw new Error('appPreset.avatar must contain at least 1 URL');
|
|
89764
|
+
}
|
|
89765
|
+
if (avatars.length > AVATAR_MAX_COUNT) {
|
|
89766
|
+
throw new Error(`appPreset.avatar supports at most ${AVATAR_MAX_COUNT} URLs, got ${avatars.length}`);
|
|
89767
|
+
}
|
|
89768
|
+
avatars.forEach((url, idx) => {
|
|
89769
|
+
if (typeof url !== 'string' || url === '') {
|
|
89770
|
+
throw new Error(`appPreset.avatar[${idx}] must be a non-empty string`);
|
|
89771
|
+
}
|
|
89772
|
+
qrCodeUrl.searchParams.append('avatar', url);
|
|
89773
|
+
});
|
|
89774
|
+
}
|
|
89775
|
+
if (name !== undefined) {
|
|
89776
|
+
qrCodeUrl.searchParams.set('name', name);
|
|
89777
|
+
}
|
|
89778
|
+
if (desc !== undefined) {
|
|
89779
|
+
qrCodeUrl.searchParams.set('desc', desc);
|
|
89780
|
+
}
|
|
89781
|
+
}
|
|
89753
89782
|
function requestRegistration(baseUrl, params) {
|
|
89754
89783
|
var _a;
|
|
89755
89784
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -89867,13 +89896,16 @@ function startPolling(ctx) {
|
|
|
89867
89896
|
function registerApp(options) {
|
|
89868
89897
|
var _a, _b, _c, _d;
|
|
89869
89898
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89870
|
-
const { domain, source, signal, onQRCodeReady, onStatusChange } = options;
|
|
89899
|
+
const { domain, source, signal, onQRCodeReady, onStatusChange, appPreset } = options;
|
|
89871
89900
|
const baseUrl = `https://${domain !== null && domain !== void 0 ? domain : DEFAULT_FEISHU_DOMAIN}`;
|
|
89872
89901
|
const beginRes = yield begin(baseUrl);
|
|
89873
89902
|
const qrCodeUrl = new URL(beginRes.verification_uri_complete);
|
|
89874
89903
|
qrCodeUrl.searchParams.set('from', 'sdk');
|
|
89875
89904
|
qrCodeUrl.searchParams.set('source', source ? `${SDK_NAME}/${source}` : SDK_NAME);
|
|
89876
89905
|
qrCodeUrl.searchParams.set('tp', 'sdk');
|
|
89906
|
+
if (appPreset) {
|
|
89907
|
+
applyAppPreset(qrCodeUrl, appPreset);
|
|
89908
|
+
}
|
|
89877
89909
|
onQRCodeReady({
|
|
89878
89910
|
url: qrCodeUrl.toString(),
|
|
89879
89911
|
expireIn: (_a = beginRes.expires_in) !== null && _a !== void 0 ? _a : 600,
|
|
@@ -89768,6 +89768,35 @@ const SDK_NAME = 'node-sdk';
|
|
|
89768
89768
|
const DEFAULT_FEISHU_DOMAIN = 'accounts.feishu.cn';
|
|
89769
89769
|
const DEFAULT_LARK_DOMAIN = 'accounts.larksuite.com';
|
|
89770
89770
|
const ENDPOINT = '/oauth/v1/app/registration';
|
|
89771
|
+
const AVATAR_MAX_COUNT = 6;
|
|
89772
|
+
/**
|
|
89773
|
+
* Append `avatar` / `name` / `desc` query params to the QR code URL.
|
|
89774
|
+
* `URLSearchParams` handles URL encoding automatically.
|
|
89775
|
+
*/
|
|
89776
|
+
function applyAppPreset(qrCodeUrl, preset) {
|
|
89777
|
+
const { avatar, name, desc } = preset;
|
|
89778
|
+
if (avatar !== undefined) {
|
|
89779
|
+
const avatars = Array.isArray(avatar) ? avatar : [avatar];
|
|
89780
|
+
if (avatars.length === 0) {
|
|
89781
|
+
throw new Error('appPreset.avatar must contain at least 1 URL');
|
|
89782
|
+
}
|
|
89783
|
+
if (avatars.length > AVATAR_MAX_COUNT) {
|
|
89784
|
+
throw new Error(`appPreset.avatar supports at most ${AVATAR_MAX_COUNT} URLs, got ${avatars.length}`);
|
|
89785
|
+
}
|
|
89786
|
+
avatars.forEach((url, idx) => {
|
|
89787
|
+
if (typeof url !== 'string' || url === '') {
|
|
89788
|
+
throw new Error(`appPreset.avatar[${idx}] must be a non-empty string`);
|
|
89789
|
+
}
|
|
89790
|
+
qrCodeUrl.searchParams.append('avatar', url);
|
|
89791
|
+
});
|
|
89792
|
+
}
|
|
89793
|
+
if (name !== undefined) {
|
|
89794
|
+
qrCodeUrl.searchParams.set('name', name);
|
|
89795
|
+
}
|
|
89796
|
+
if (desc !== undefined) {
|
|
89797
|
+
qrCodeUrl.searchParams.set('desc', desc);
|
|
89798
|
+
}
|
|
89799
|
+
}
|
|
89771
89800
|
function requestRegistration(baseUrl, params) {
|
|
89772
89801
|
var _a;
|
|
89773
89802
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -89885,13 +89914,16 @@ function startPolling(ctx) {
|
|
|
89885
89914
|
function registerApp(options) {
|
|
89886
89915
|
var _a, _b, _c, _d;
|
|
89887
89916
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89888
|
-
const { domain, source, signal, onQRCodeReady, onStatusChange } = options;
|
|
89917
|
+
const { domain, source, signal, onQRCodeReady, onStatusChange, appPreset } = options;
|
|
89889
89918
|
const baseUrl = `https://${domain !== null && domain !== void 0 ? domain : DEFAULT_FEISHU_DOMAIN}`;
|
|
89890
89919
|
const beginRes = yield begin(baseUrl);
|
|
89891
89920
|
const qrCodeUrl = new URL(beginRes.verification_uri_complete);
|
|
89892
89921
|
qrCodeUrl.searchParams.set('from', 'sdk');
|
|
89893
89922
|
qrCodeUrl.searchParams.set('source', source ? `${SDK_NAME}/${source}` : SDK_NAME);
|
|
89894
89923
|
qrCodeUrl.searchParams.set('tp', 'sdk');
|
|
89924
|
+
if (appPreset) {
|
|
89925
|
+
applyAppPreset(qrCodeUrl, appPreset);
|
|
89926
|
+
}
|
|
89895
89927
|
onQRCodeReady({
|
|
89896
89928
|
url: qrCodeUrl.toString(),
|
|
89897
89929
|
expireIn: (_a = beginRes.expires_in) !== null && _a !== void 0 ? _a : 600,
|
|
@@ -300741,6 +300741,23 @@ interface StatusChangeInfo {
|
|
|
300741
300741
|
status: 'polling' | 'slow_down' | 'domain_switched';
|
|
300742
300742
|
interval?: number;
|
|
300743
300743
|
}
|
|
300744
|
+
/**
|
|
300745
|
+
* Pre-fill values shown on the app-creation page after the user scans the QR
|
|
300746
|
+
* code. All fields are optional and the user can still edit them on the page;
|
|
300747
|
+
* the final values are whatever the user submits.
|
|
300748
|
+
*/
|
|
300749
|
+
interface AppPreset {
|
|
300750
|
+
/**
|
|
300751
|
+
* App avatar URL(s). Pass a single URL or 1-6 URLs. The first one is the
|
|
300752
|
+
* default selection. Each URL must point to a publicly reachable image
|
|
300753
|
+
* (png / jpg / jpeg / webp / gif).
|
|
300754
|
+
*/
|
|
300755
|
+
avatar?: string | string[];
|
|
300756
|
+
/** App name. Supports `{user}` placeholder, replaced with the scanning user's name. */
|
|
300757
|
+
name?: string;
|
|
300758
|
+
/** App description. Supports `{user}` placeholder. */
|
|
300759
|
+
desc?: string;
|
|
300760
|
+
}
|
|
300744
300761
|
interface RegisterAppOptions {
|
|
300745
300762
|
domain?: string;
|
|
300746
300763
|
larkDomain?: string;
|
|
@@ -300748,6 +300765,8 @@ interface RegisterAppOptions {
|
|
|
300748
300765
|
signal?: AbortSignal;
|
|
300749
300766
|
onQRCodeReady: (info: QRCodeInfo) => void;
|
|
300750
300767
|
onStatusChange?: (info: StatusChangeInfo) => void;
|
|
300768
|
+
/** Pre-fill values for the app-creation page. See {@link AppPreset}. */
|
|
300769
|
+
appPreset?: AppPreset;
|
|
300751
300770
|
}
|
|
300752
300771
|
interface UserInfo {
|
|
300753
300772
|
open_id?: string;
|