@insta-dev01/insta-plugin-openclaw 1.0.0 → 1.0.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.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/src/channel/config.d.ts +9 -0
- package/dist/src/channel/config.d.ts.map +1 -0
- package/dist/src/channel/config.js +10 -0
- package/dist/src/channel/config.js.map +1 -0
- package/dist/src/channel/connection.d.ts +34 -0
- package/dist/src/channel/connection.d.ts.map +1 -0
- package/dist/src/channel/connection.js +281 -0
- package/dist/src/channel/connection.js.map +1 -0
- package/dist/src/channel/dispatcher.d.ts +43 -0
- package/dist/src/channel/dispatcher.d.ts.map +1 -0
- package/dist/src/channel/dispatcher.js +324 -0
- package/dist/src/channel/dispatcher.js.map +1 -0
- package/dist/src/channel/index.d.ts +5 -0
- package/dist/src/channel/index.d.ts.map +1 -0
- package/dist/src/channel/index.js +135 -0
- package/dist/src/channel/index.js.map +1 -0
- package/dist/src/channel/logger.d.ts +10 -0
- package/dist/src/channel/logger.d.ts.map +1 -0
- package/dist/src/channel/logger.js +30 -0
- package/dist/src/channel/logger.js.map +1 -0
- package/dist/src/channel/protocol.d.ts +15 -0
- package/dist/src/channel/protocol.d.ts.map +1 -0
- package/dist/src/channel/protocol.js +204 -0
- package/dist/src/channel/protocol.js.map +1 -0
- package/dist/src/channel/registrar.d.ts +21 -0
- package/dist/src/channel/registrar.d.ts.map +1 -0
- package/dist/src/channel/registrar.js +115 -0
- package/dist/src/channel/registrar.js.map +1 -0
- package/dist/src/channel/registration-store.d.ts +21 -0
- package/dist/src/channel/registration-store.d.ts.map +1 -0
- package/{src/channel/registration-store.ts → dist/src/channel/registration-store.js} +21 -46
- package/dist/src/channel/registration-store.js.map +1 -0
- package/dist/src/channel/types.d.ts +80 -0
- package/dist/src/channel/types.d.ts.map +1 -0
- package/dist/src/channel/types.js +3 -0
- package/dist/src/channel/types.js.map +1 -0
- package/dist/src/core/index.d.ts +5 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +3 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/register-identity.d.ts +58 -0
- package/dist/src/core/register-identity.d.ts.map +1 -0
- package/dist/src/core/register-identity.js +251 -0
- package/dist/src/core/register-identity.js.map +1 -0
- package/dist/src/core/task-api.d.ts +31 -0
- package/dist/src/core/task-api.d.ts.map +1 -0
- package/dist/src/core/task-api.js +116 -0
- package/dist/src/core/task-api.js.map +1 -0
- package/dist/src/core/urls.d.ts +33 -0
- package/dist/src/core/urls.d.ts.map +1 -0
- package/dist/src/core/urls.js +40 -0
- package/dist/src/core/urls.js.map +1 -0
- package/dist/src/tools/get-plugin-profile.d.ts +7 -0
- package/dist/src/tools/get-plugin-profile.d.ts.map +1 -0
- package/dist/src/tools/get-plugin-profile.js +132 -0
- package/dist/src/tools/get-plugin-profile.js.map +1 -0
- package/dist/src/tools/grab-task.d.ts +7 -0
- package/dist/src/tools/grab-task.d.ts.map +1 -0
- package/dist/src/tools/grab-task.js +100 -0
- package/dist/src/tools/grab-task.js.map +1 -0
- package/dist/src/tools/list-tasks.d.ts +7 -0
- package/dist/src/tools/list-tasks.d.ts.map +1 -0
- package/dist/src/tools/list-tasks.js +92 -0
- package/dist/src/tools/list-tasks.js.map +1 -0
- package/dist/src/tools/propose-registration.d.ts +14 -0
- package/dist/src/tools/propose-registration.d.ts.map +1 -0
- package/dist/src/tools/propose-registration.js +103 -0
- package/dist/src/tools/propose-registration.js.map +1 -0
- package/dist/src/tools/register-identity.d.ts +11 -0
- package/dist/src/tools/register-identity.d.ts.map +1 -0
- package/dist/src/tools/register-identity.js +101 -0
- package/dist/src/tools/register-identity.js.map +1 -0
- package/dist/src/tools/submit-deliverable.d.ts +17 -0
- package/dist/src/tools/submit-deliverable.d.ts.map +1 -0
- package/dist/src/tools/submit-deliverable.js +215 -0
- package/dist/src/tools/submit-deliverable.js.map +1 -0
- package/dist/src/tools/upload-artifact.d.ts +14 -0
- package/dist/src/tools/upload-artifact.d.ts.map +1 -0
- package/dist/src/tools/upload-artifact.js +166 -0
- package/dist/src/tools/upload-artifact.js.map +1 -0
- package/dist/src/utils/file-lock.d.ts +4 -0
- package/dist/src/utils/file-lock.d.ts.map +1 -0
- package/dist/src/utils/file-lock.js +43 -0
- package/dist/src/utils/file-lock.js.map +1 -0
- package/dist/src/utils/profile.d.ts +17 -0
- package/dist/src/utils/profile.d.ts.map +1 -0
- package/dist/src/utils/profile.js +26 -0
- package/dist/src/utils/profile.js.map +1 -0
- package/dist/src/utils/session.d.ts +3 -0
- package/dist/src/utils/session.d.ts.map +1 -0
- package/dist/src/utils/session.js +26 -0
- package/dist/src/utils/session.js.map +1 -0
- package/package.json +17 -5
- package/.env.example +0 -23
- package/channel/346/265/201/347/250/213/345/233/276.md +0 -477
- package/index.ts +0 -198
- package/src/channel/config.ts +0 -27
- package/src/channel/connection.ts +0 -341
- package/src/channel/dispatcher.ts +0 -374
- package/src/channel/index.ts +0 -173
- package/src/channel/logger.ts +0 -36
- package/src/channel/protocol.ts +0 -265
- package/src/channel/registrar.ts +0 -172
- package/src/channel/types.ts +0 -102
- package/src/core/index.ts +0 -13
- package/src/core/register-identity.ts +0 -326
- package/src/core/task-api.ts +0 -168
- package/src/core/urls.ts +0 -52
- package/src/prompt/job.md +0 -21
- package/src/tools/get-plugin-profile.ts +0 -152
- package/src/tools/grab-task.ts +0 -133
- package/src/tools/list-tasks.ts +0 -135
- package/src/tools/propose-registration.ts +0 -116
- package/src/tools/register-identity.ts +0 -121
- package/src/tools/submit-deliverable.ts +0 -268
- package/src/tools/upload-artifact.ts +0 -222
- package/src/utils/file-lock.ts +0 -43
- package/src/utils/profile.ts +0 -45
- package/src/utils/session.ts +0 -30
- package/tests/profile.test.ts +0 -70
- package/tests/session.test.ts +0 -53
- package/tsconfig.json +0 -49
- package/vitest.config.ts +0 -26
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenClawPluginToolContext,
|
|
3
|
-
OpenClawPluginToolFactory,
|
|
4
|
-
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
|
-
import { readProfile } from "../utils/profile.js";
|
|
6
|
-
import { readSession } from "../utils/session.js";
|
|
7
|
-
|
|
8
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
9
|
-
// 敏感字段白名单:这些字段的值会被 * 号掩码处理
|
|
10
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
11
|
-
const SENSITIVE_KEYS: Set<string> = new Set(["app_secret"]);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 对字符串值进行脱敏:
|
|
15
|
-
* - 保留前 2 个字符,其余替换为 *
|
|
16
|
-
* - 若值 ≤ 4 个字符,则全部替换
|
|
17
|
-
*/
|
|
18
|
-
function maskSecret(value: string): string {
|
|
19
|
-
if (!value) return value;
|
|
20
|
-
if (value.length <= 4) return "*".repeat(value.length);
|
|
21
|
-
return value.slice(0, 2) + "*".repeat(value.length - 2);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 对 Record 对象中 SENSITIVE_KEYS 里的字段进行打码,返回新对象(不修改原始数据)。
|
|
26
|
-
*/
|
|
27
|
-
function maskSensitiveFields(
|
|
28
|
-
obj: Record<string, unknown>,
|
|
29
|
-
): Record<string, unknown> {
|
|
30
|
-
const result: Record<string, unknown> = {};
|
|
31
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
32
|
-
if (SENSITIVE_KEYS.has(key) && typeof value === "string") {
|
|
33
|
-
result[key] = maskSecret(value);
|
|
34
|
-
} else {
|
|
35
|
-
result[key] = value;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return result;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 对 session token 进行脱敏:保留前 4 个字符,其余替换为 *
|
|
43
|
-
*/
|
|
44
|
-
function maskSessionToken(token: string): string {
|
|
45
|
-
if (!token) return token;
|
|
46
|
-
if (token.length <= 4) return "*".repeat(token.length);
|
|
47
|
-
return token.slice(0, 4) + "*".repeat(token.length - 4);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
51
|
-
// 工具:insta_get_plugin_profile
|
|
52
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
53
|
-
|
|
54
|
-
/** 工具的空参数 JSON Schema(无需任何输入参数)*/
|
|
55
|
-
const EMPTY_PARAMS = {
|
|
56
|
-
type: "object" as const,
|
|
57
|
-
properties: {},
|
|
58
|
-
required: [] as string[],
|
|
59
|
-
additionalProperties: false,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 工具工厂函数。
|
|
64
|
-
* 在 index.ts 中通过 api.registerTool(getPluginProfileToolFactory) 注册。
|
|
65
|
-
*/
|
|
66
|
-
export const getPluginProfileToolFactory: OpenClawPluginToolFactory = (
|
|
67
|
-
ctx: OpenClawPluginToolContext,
|
|
68
|
-
) => {
|
|
69
|
-
return {
|
|
70
|
-
name: "insta_get_plugin_profile",
|
|
71
|
-
label: "获取引态插件配置与注册状态",
|
|
72
|
-
description: [
|
|
73
|
-
"查询引态(Instaon)OpenClaw 插件的基础配置信息和服务端注册状态。",
|
|
74
|
-
"返回以下数据:",
|
|
75
|
-
" · profile(插件配置):app_key、name、description、claw_id、hourly_rate、",
|
|
76
|
-
" enable_commissioned、enable_hired、scene_tags、custom_tags、avatar、instance_type 等。",
|
|
77
|
-
" 敏感字段(如 app_secret)以 * 号掩码返回,不会暴露明文。",
|
|
78
|
-
" · session(注册状态):服务端颁发的激活 token(脱敏);未注册时为 null。",
|
|
79
|
-
" · registered:布尔值,表示插件是否已成功在引态平台完成服务端注册。",
|
|
80
|
-
"适用场景:排查插件配置、确认服务端注册是否成功。",
|
|
81
|
-
].join("\n"),
|
|
82
|
-
|
|
83
|
-
// 该工具不需要任何输入参数
|
|
84
|
-
parameters: EMPTY_PARAMS,
|
|
85
|
-
|
|
86
|
-
execute: async (_toolCallId: string, _params: unknown) => {
|
|
87
|
-
// 优先使用 agentDir(工作目录),其次 workspaceDir,最后 cwd
|
|
88
|
-
const baseDir = ctx.agentDir ?? ctx.workspaceDir ?? process.cwd();
|
|
89
|
-
|
|
90
|
-
// 并行读取 profile 与 session
|
|
91
|
-
const [profile, sessionToken] = await Promise.all([
|
|
92
|
-
readProfile(baseDir),
|
|
93
|
-
readSession(baseDir),
|
|
94
|
-
]);
|
|
95
|
-
|
|
96
|
-
// profile 不存在时的错误响应
|
|
97
|
-
if (!profile) {
|
|
98
|
-
const errorResult = {
|
|
99
|
-
success: false,
|
|
100
|
-
error:
|
|
101
|
-
"未找到插件配置文件(.insta/config/profile.json)。" +
|
|
102
|
-
"请先通过引态平台完成初始化配置。",
|
|
103
|
-
registered: false,
|
|
104
|
-
profile: null,
|
|
105
|
-
session: null,
|
|
106
|
-
};
|
|
107
|
-
return {
|
|
108
|
-
content: [
|
|
109
|
-
{
|
|
110
|
-
type: "text" as const,
|
|
111
|
-
text: JSON.stringify(errorResult, null, 2),
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
details: errorResult,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// 对 profile 字段进行脱敏
|
|
119
|
-
const safeProfile = maskSensitiveFields(
|
|
120
|
-
profile as unknown as Record<string, unknown>,
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
// 对 session token 进行脱敏
|
|
124
|
-
const safeSession = sessionToken
|
|
125
|
-
? {
|
|
126
|
-
token: maskSessionToken(sessionToken),
|
|
127
|
-
status: "已激活",
|
|
128
|
-
}
|
|
129
|
-
: {
|
|
130
|
-
token: null,
|
|
131
|
-
status: "未注册",
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const successResult = {
|
|
135
|
-
success: true,
|
|
136
|
-
registered: !!sessionToken,
|
|
137
|
-
profile: safeProfile,
|
|
138
|
-
session: safeSession,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
content: [
|
|
143
|
-
{
|
|
144
|
-
type: "text" as const,
|
|
145
|
-
text: JSON.stringify(successResult, null, 2),
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
details: successResult,
|
|
149
|
-
};
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
};
|
package/src/tools/grab-task.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenClawPluginToolContext,
|
|
3
|
-
OpenClawPluginToolFactory,
|
|
4
|
-
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
|
-
import { taskApiPost } from "../core/task-api.js";
|
|
6
|
-
|
|
7
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
8
|
-
// 响应数据类型
|
|
9
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
/** 抢单成功时 data 字段结构 */
|
|
12
|
-
interface GrabSuccessData {
|
|
13
|
-
task_id: string;
|
|
14
|
-
grab_time: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 服务端已知错误码
|
|
18
|
-
const ERROR_CODE_MESSAGES: Record<number, string> = {
|
|
19
|
-
40001: "任务已被其他 Bot 抢先认领(task_already_grabbed)",
|
|
20
|
-
40002: "任务当前不可认领,可能已过期或状态异常(task_not_available)",
|
|
21
|
-
40003: "任务不存在(task_not_found)",
|
|
22
|
-
40100: "未授权,请检查 app_key / app_secret 配置(unauthorized)",
|
|
23
|
-
40101: "API Key 或 Secret 无效(invalid_credentials)",
|
|
24
|
-
40102: "Bot 尚未激活(bot_inactive)",
|
|
25
|
-
40103: "Bot 尚未审核通过(bot_not_approved)",
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
29
|
-
// 工具参数 JSON Schema
|
|
30
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
const GRAB_TASK_PARAMS = {
|
|
33
|
-
type: "object" as const,
|
|
34
|
-
properties: {
|
|
35
|
-
task_id: {
|
|
36
|
-
type: "string",
|
|
37
|
-
description:
|
|
38
|
-
"需要认领的任务 UUID,可通过 insta_list_tasks 工具获取。",
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
required: ["task_id"] as string[],
|
|
42
|
-
additionalProperties: false,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
46
|
-
// 工具:insta_grab_task
|
|
47
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 任务抢单工具工厂函数。
|
|
51
|
-
* 在 index.ts 中通过 api.registerTool(grabTaskToolFactory) 注册。
|
|
52
|
-
*/
|
|
53
|
-
export const grabTaskToolFactory: OpenClawPluginToolFactory = (
|
|
54
|
-
ctx: OpenClawPluginToolContext,
|
|
55
|
-
) => {
|
|
56
|
-
return {
|
|
57
|
-
name: "insta_grab_task",
|
|
58
|
-
label: "认领引态任务池中的任务(抢单)",
|
|
59
|
-
description: [
|
|
60
|
-
"向引态(Instaon)任务系统发起抢单请求,将指定任务标记为「已认领」状态。",
|
|
61
|
-
"抢单成功后,该任务归属于当前 Bot(claw_id),可继续执行并提交产物。",
|
|
62
|
-
"参数说明:",
|
|
63
|
-
" · task_id(必填):目标任务的 UUID,可通过 insta_list_tasks 工具查询获取。",
|
|
64
|
-
"返回说明:",
|
|
65
|
-
" · ok=true:抢单成功,data 中包含 task_id 和 grab_time。",
|
|
66
|
-
" · ok=false:抢单失败,error 中包含具体原因(如已被抢、不可认领等)。",
|
|
67
|
-
"认证方式:自动读取本地 profile.json 中的 app_key / app_secret。",
|
|
68
|
-
].join("\n"),
|
|
69
|
-
|
|
70
|
-
parameters: GRAB_TASK_PARAMS,
|
|
71
|
-
|
|
72
|
-
execute: async (_toolCallId: string, params: unknown) => {
|
|
73
|
-
try {
|
|
74
|
-
const p = params as Record<string, unknown>;
|
|
75
|
-
const taskId =
|
|
76
|
-
typeof p["task_id"] === "string" ? p["task_id"].trim() : "";
|
|
77
|
-
|
|
78
|
-
// ── 参数校验 ──────────────────────────────────────────────────────────
|
|
79
|
-
if (!taskId) {
|
|
80
|
-
const err = { ok: false, error: "缺少必填参数:task_id(任务 UUID)" };
|
|
81
|
-
return {
|
|
82
|
-
content: [{ type: "text" as const, text: JSON.stringify(err) }],
|
|
83
|
-
details: err,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const baseDir = ctx.agentDir ?? ctx.workspaceDir ?? process.cwd();
|
|
88
|
-
|
|
89
|
-
const resp = await taskApiPost<GrabSuccessData>(
|
|
90
|
-
baseDir,
|
|
91
|
-
`/bots/tasks/${taskId}/grab`,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// ── 抢单成功 ──────────────────────────────────────────────────────────
|
|
95
|
-
if (resp.code === 0) {
|
|
96
|
-
const result = {
|
|
97
|
-
ok: true,
|
|
98
|
-
task_id: resp.data?.task_id ?? taskId,
|
|
99
|
-
grab_time: resp.data?.grab_time ?? null,
|
|
100
|
-
message: "抢单成功,任务已标记为已认领状态",
|
|
101
|
-
};
|
|
102
|
-
return {
|
|
103
|
-
content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
|
|
104
|
-
details: result,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ── 抢单失败(业务错误) ───────────────────────────────────────────────
|
|
109
|
-
const humanMessage =
|
|
110
|
-
ERROR_CODE_MESSAGES[resp.code] ??
|
|
111
|
-
`抢单失败(code=${resp.code},message=${resp.message})`;
|
|
112
|
-
|
|
113
|
-
const err = {
|
|
114
|
-
ok: false,
|
|
115
|
-
code: resp.code,
|
|
116
|
-
error: humanMessage,
|
|
117
|
-
raw_message: resp.message,
|
|
118
|
-
};
|
|
119
|
-
return {
|
|
120
|
-
content: [{ type: "text" as const, text: JSON.stringify(err, null, 2) }],
|
|
121
|
-
details: err,
|
|
122
|
-
};
|
|
123
|
-
} catch (e: unknown) {
|
|
124
|
-
const message = e instanceof Error ? e.message : "抢单过程中发生未知错误";
|
|
125
|
-
const err = { ok: false, error: message };
|
|
126
|
-
return {
|
|
127
|
-
content: [{ type: "text" as const, text: message }],
|
|
128
|
-
details: err,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
};
|
package/src/tools/list-tasks.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenClawPluginToolContext,
|
|
3
|
-
OpenClawPluginToolFactory,
|
|
4
|
-
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
|
-
import { taskApiGet } from "../core/task-api.js";
|
|
6
|
-
|
|
7
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
8
|
-
// 响应数据类型
|
|
9
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
/** 任务池单条任务摘要(与 API 文档字段对应) */
|
|
12
|
-
interface TaskSummary {
|
|
13
|
-
id: string;
|
|
14
|
-
title: string;
|
|
15
|
-
category: string;
|
|
16
|
-
bounty: string | number;
|
|
17
|
-
deadline: string;
|
|
18
|
-
created_at: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** 任务列表分页响应 data 字段 */
|
|
22
|
-
interface TaskListData {
|
|
23
|
-
items: TaskSummary[];
|
|
24
|
-
total: number;
|
|
25
|
-
page: number;
|
|
26
|
-
page_size: number;
|
|
27
|
-
total_pages: number | null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
31
|
-
// 工具参数 JSON Schema
|
|
32
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
33
|
-
|
|
34
|
-
const LIST_TASKS_PARAMS = {
|
|
35
|
-
type: "object" as const,
|
|
36
|
-
properties: {
|
|
37
|
-
page: {
|
|
38
|
-
type: "number",
|
|
39
|
-
description: "页码,从 1 开始,默认为 1",
|
|
40
|
-
},
|
|
41
|
-
page_size: {
|
|
42
|
-
type: "number",
|
|
43
|
-
description: "每页返回的任务数量,范围 1~100,默认为 20",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
required: [] as string[],
|
|
47
|
-
additionalProperties: false,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
51
|
-
// 工具:insta_list_tasks
|
|
52
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 查询引态任务池可接单任务列表工具工厂函数。
|
|
56
|
-
* 在 index.ts 中通过 api.registerTool(listTasksToolFactory) 注册。
|
|
57
|
-
*/
|
|
58
|
-
export const listTasksToolFactory: OpenClawPluginToolFactory = (
|
|
59
|
-
ctx: OpenClawPluginToolContext,
|
|
60
|
-
) => {
|
|
61
|
-
return {
|
|
62
|
-
name: "insta_list_tasks",
|
|
63
|
-
label: "查询引态任务池可接单列表",
|
|
64
|
-
description: [
|
|
65
|
-
"查询引态(Instaon)任务池中当前可供 Bot 认领的任务列表。",
|
|
66
|
-
"返回任务的基础摘要信息,包括:",
|
|
67
|
-
" · id:任务唯一 ID(UUID),抢单时需要传入此值。",
|
|
68
|
-
" · title:任务标题。",
|
|
69
|
-
" · category:任务分类。",
|
|
70
|
-
" · bounty:赏金(元)。",
|
|
71
|
-
" · deadline:截止时间(ISO 8601 格式)。",
|
|
72
|
-
" · created_at:任务创建时间。",
|
|
73
|
-
"参数说明:",
|
|
74
|
-
" · page(可选):页码,默认 1。",
|
|
75
|
-
" · page_size(可选):每页数量,默认 20,最大 100。",
|
|
76
|
-
"认证方式:自动读取本地 profile.json 中的 app_key / app_secret。",
|
|
77
|
-
].join("\n"),
|
|
78
|
-
|
|
79
|
-
parameters: LIST_TASKS_PARAMS,
|
|
80
|
-
|
|
81
|
-
execute: async (_toolCallId: string, params: unknown) => {
|
|
82
|
-
try {
|
|
83
|
-
const p = (params ?? {}) as Record<string, unknown>;
|
|
84
|
-
const page = typeof p["page"] === "number" ? Math.max(1, Math.floor(p["page"])) : 1;
|
|
85
|
-
const pageSize =
|
|
86
|
-
typeof p["page_size"] === "number"
|
|
87
|
-
? Math.min(100, Math.max(1, Math.floor(p["page_size"])))
|
|
88
|
-
: 20;
|
|
89
|
-
|
|
90
|
-
const baseDir = ctx.agentDir ?? ctx.workspaceDir ?? process.cwd();
|
|
91
|
-
|
|
92
|
-
const resp = await taskApiGet<TaskListData>(
|
|
93
|
-
baseDir,
|
|
94
|
-
"/bots/tasks/available",
|
|
95
|
-
{ page, page_size: pageSize },
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
// 服务端业务错误(code !== 0)
|
|
99
|
-
if (resp.code !== 0) {
|
|
100
|
-
const err = {
|
|
101
|
-
ok: false,
|
|
102
|
-
code: resp.code,
|
|
103
|
-
error: resp.message ?? "查询任务列表失败",
|
|
104
|
-
data: null,
|
|
105
|
-
};
|
|
106
|
-
return {
|
|
107
|
-
content: [{ type: "text" as const, text: JSON.stringify(err, null, 2) }],
|
|
108
|
-
details: err,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const result = {
|
|
113
|
-
ok: true,
|
|
114
|
-
total: resp.data?.total ?? 0,
|
|
115
|
-
page: resp.data?.page ?? page,
|
|
116
|
-
page_size: resp.data?.page_size ?? pageSize,
|
|
117
|
-
total_pages: resp.data?.total_pages ?? null,
|
|
118
|
-
items: resp.data?.items ?? [],
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
|
|
123
|
-
details: result,
|
|
124
|
-
};
|
|
125
|
-
} catch (e: unknown) {
|
|
126
|
-
const message = e instanceof Error ? e.message : "查询任务列表时发生未知错误";
|
|
127
|
-
const err = { ok: false, error: message };
|
|
128
|
-
return {
|
|
129
|
-
content: [{ type: "text" as const, text: message }],
|
|
130
|
-
details: err,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenClawPluginToolContext,
|
|
3
|
-
OpenClawPluginToolFactory,
|
|
4
|
-
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
|
-
import { VALID_SCENE_TAG_IDS } from "../core/register-identity.js";
|
|
6
|
-
import { setPendingRegistration } from "../channel/registration-store.js";
|
|
7
|
-
|
|
8
|
-
// ── Parameters schema (mirrors register-identity params) ──────────────────────
|
|
9
|
-
|
|
10
|
-
const PARAMS_SCHEMA = {
|
|
11
|
-
type: "object" as const,
|
|
12
|
-
properties: {
|
|
13
|
-
name: {
|
|
14
|
-
type: "string",
|
|
15
|
-
description: "档案名称",
|
|
16
|
-
},
|
|
17
|
-
avatar: {
|
|
18
|
-
type: "string",
|
|
19
|
-
description: "头像图片 URL(必须是可访问的合法 URL)",
|
|
20
|
-
},
|
|
21
|
-
description: {
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "服务描述",
|
|
24
|
-
},
|
|
25
|
-
hourly_rate: {
|
|
26
|
-
type: "number",
|
|
27
|
-
description: "时薪(必须 > 0,单位:元)",
|
|
28
|
-
},
|
|
29
|
-
scene_tags: {
|
|
30
|
-
type: "array",
|
|
31
|
-
items: { type: "string" },
|
|
32
|
-
description: `场景标签 ID 数组(1-3 个)。合法值:${[...VALID_SCENE_TAG_IDS].join(", ")}`,
|
|
33
|
-
},
|
|
34
|
-
custom_tags: {
|
|
35
|
-
type: "array",
|
|
36
|
-
items: { type: "string" },
|
|
37
|
-
description: "自定义标签列表(可选)",
|
|
38
|
-
},
|
|
39
|
-
instance_type: {
|
|
40
|
-
type: "number",
|
|
41
|
-
enum: [0, 1],
|
|
42
|
-
description: "实例类型:0 = 本地实例(推荐),1 = 影子实例",
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
required: ["name", "avatar", "description", "hourly_rate", "scene_tags", "instance_type"] as string[],
|
|
46
|
-
additionalProperties: false,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// ── Tool factory ──────────────────────────────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Tool: insta_propose_registration
|
|
53
|
-
*
|
|
54
|
-
* Stores AI-suggested registration parameters as a "pending confirmation" record.
|
|
55
|
-
* The host will surface a Control UI component to the user so they can review,
|
|
56
|
-
* optionally edit, and then confirm the parameters via the
|
|
57
|
-
* `instaclaw.registration.submit` gateway method.
|
|
58
|
-
*
|
|
59
|
-
* This tool does NOT perform the actual registration. Use it when you want to
|
|
60
|
-
* let the user review before committing.
|
|
61
|
-
*/
|
|
62
|
-
export const proposeRegistrationToolFactory: OpenClawPluginToolFactory = (
|
|
63
|
-
_ctx: OpenClawPluginToolContext,
|
|
64
|
-
) => {
|
|
65
|
-
return {
|
|
66
|
-
name: "insta_propose_registration",
|
|
67
|
-
label: "提交 InstaClaw 注册提案",
|
|
68
|
-
description: [
|
|
69
|
-
'将建议的 InstaClaw 注册参数暂存为"待用户确认"状态。',
|
|
70
|
-
"调用后,控制面板会显示一个确认表单,用户可在其中查看、修改参数,",
|
|
71
|
-
'然后点击"确认注册"完成注册。',
|
|
72
|
-
"",
|
|
73
|
-
"此工具不会立即注册,仅用于暂存建议参数供用户审阅。",
|
|
74
|
-
"",
|
|
75
|
-
"参数:",
|
|
76
|
-
" · name(必填):档案名称",
|
|
77
|
-
" · avatar(必填):头像 URL",
|
|
78
|
-
" · description(必填):服务描述",
|
|
79
|
-
" · hourly_rate(必填):时薪,必须 > 0",
|
|
80
|
-
" · scene_tags(必填):场景标签 ID 数组(1-3 个)",
|
|
81
|
-
" · custom_tags(可选):自定义标签",
|
|
82
|
-
" · instance_type(必填):0 = 本地实例,1 = 影子实例",
|
|
83
|
-
].join("\n"),
|
|
84
|
-
parameters: PARAMS_SCHEMA,
|
|
85
|
-
|
|
86
|
-
execute: async (_toolCallId, params) => {
|
|
87
|
-
const p = params as Record<string, unknown>;
|
|
88
|
-
|
|
89
|
-
setPendingRegistration({
|
|
90
|
-
name: p["name"] as string,
|
|
91
|
-
avatar: p["avatar"] as string,
|
|
92
|
-
description: p["description"] as string,
|
|
93
|
-
hourly_rate: p["hourly_rate"] as number,
|
|
94
|
-
scene_tags: p["scene_tags"] as string[],
|
|
95
|
-
custom_tags: p["custom_tags"] as string[] | undefined,
|
|
96
|
-
instance_type: p["instance_type"] as 0 | 1,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
const successText = [
|
|
100
|
-
"注册信息已暂存 ✓",
|
|
101
|
-
"",
|
|
102
|
-
`名称:${p["name"]}`,
|
|
103
|
-
`时薪:${p["hourly_rate"]} 元`,
|
|
104
|
-
`场景标签:${(p["scene_tags"] as string[]).join(", ")}`,
|
|
105
|
-
`实例类型:${p["instance_type"] === 0 ? "本地实例" : "影子实例"}`,
|
|
106
|
-
"",
|
|
107
|
-
"请在控制面板的「InstaClaw 服务注册」卡片中确认信息,点击「确认注册」完成注册。",
|
|
108
|
-
].join("\n");
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
content: [{ type: "text" as const, text: successText }],
|
|
112
|
-
details: { stored: true },
|
|
113
|
-
};
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenClawPluginToolContext,
|
|
3
|
-
OpenClawPluginToolFactory,
|
|
4
|
-
} from "openclaw/plugin-sdk/plugin-entry";
|
|
5
|
-
import {
|
|
6
|
-
registerIdentity,
|
|
7
|
-
VALID_SCENE_TAG_IDS,
|
|
8
|
-
} from "../core/register-identity.js";
|
|
9
|
-
|
|
10
|
-
// ── Parameters schema ─────────────────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
const PARAMS_SCHEMA = {
|
|
13
|
-
type: "object" as const,
|
|
14
|
-
properties: {
|
|
15
|
-
name: {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "档案名称",
|
|
18
|
-
},
|
|
19
|
-
avatar: {
|
|
20
|
-
type: "string",
|
|
21
|
-
description: "头像图片 URL(必须是可访问的合法 URL)",
|
|
22
|
-
},
|
|
23
|
-
description: {
|
|
24
|
-
type: "string",
|
|
25
|
-
description: "服务描述",
|
|
26
|
-
},
|
|
27
|
-
hourly_rate: {
|
|
28
|
-
type: "number",
|
|
29
|
-
description: "时薪(必须 > 0,单位:元)",
|
|
30
|
-
},
|
|
31
|
-
scene_tags: {
|
|
32
|
-
type: "array",
|
|
33
|
-
items: { type: "string" },
|
|
34
|
-
description: `场景标签 ID 数组(1-3 个)。合法值:${[...VALID_SCENE_TAG_IDS].join(", ")}`,
|
|
35
|
-
},
|
|
36
|
-
custom_tags: {
|
|
37
|
-
type: "array",
|
|
38
|
-
items: { type: "string" },
|
|
39
|
-
description: "自定义标签列表(可选)",
|
|
40
|
-
},
|
|
41
|
-
instance_type: {
|
|
42
|
-
type: "number",
|
|
43
|
-
enum: [0, 1],
|
|
44
|
-
description: "实例类型:0 = 本地实例(推荐),1 = 影子实例",
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
required: ["name", "avatar", "description", "hourly_rate", "scene_tags", "instance_type"] as string[],
|
|
48
|
-
additionalProperties: false,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// ── Tool factory ──────────────────────────────────────────────────────────────
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Tool: insta_register_identity
|
|
55
|
-
*
|
|
56
|
-
* Registers an InstaClaw profile via POST /profiles/create and persists the
|
|
57
|
-
* resulting credentials to the local profile file. Once registered, the
|
|
58
|
-
* channel's 10-second polling loop will detect the credentials and
|
|
59
|
-
* automatically establish the WebSocket connection.
|
|
60
|
-
*/
|
|
61
|
-
export const registerIdentityToolFactory: OpenClawPluginToolFactory = (
|
|
62
|
-
ctx: OpenClawPluginToolContext,
|
|
63
|
-
) => {
|
|
64
|
-
return {
|
|
65
|
-
name: "insta_register_identity",
|
|
66
|
-
label: "注册 InstaClaw 档案",
|
|
67
|
-
description: [
|
|
68
|
-
"向 InstaClaw 平台注册服务档案,完成频道初始化配置。",
|
|
69
|
-
"注册成功后,凭证将保存到本地 profile 文件,",
|
|
70
|
-
"InstaClaw channel 会在 10 秒内自动检测并建立 WebSocket 连接。",
|
|
71
|
-
"",
|
|
72
|
-
"参数:",
|
|
73
|
-
" · name(必填):档案名称",
|
|
74
|
-
" · avatar(必填):头像 URL",
|
|
75
|
-
" · description(必填):服务描述",
|
|
76
|
-
" · hourly_rate(必填):时薪,必须 > 0",
|
|
77
|
-
" · scene_tags(必填):场景标签 ID 数组",
|
|
78
|
-
" · custom_tags(可选):自定义标签",
|
|
79
|
-
" · instance_type(必填):0 = 本地实例,1 = 影子实例",
|
|
80
|
-
].join("\n"),
|
|
81
|
-
parameters: PARAMS_SCHEMA,
|
|
82
|
-
|
|
83
|
-
execute: async (_toolCallId, params) => {
|
|
84
|
-
const baseDir = ctx.agentDir ?? ctx.workspaceDir ?? process.cwd();
|
|
85
|
-
const p = params as Record<string, unknown>;
|
|
86
|
-
|
|
87
|
-
const result = await registerIdentity(
|
|
88
|
-
{
|
|
89
|
-
name: p["name"] as string,
|
|
90
|
-
avatar: p["avatar"] as string,
|
|
91
|
-
description: p["description"] as string,
|
|
92
|
-
hourly_rate: p["hourly_rate"] as number,
|
|
93
|
-
scene_tags: p["scene_tags"] as string[],
|
|
94
|
-
custom_tags: p["custom_tags"] as string[] | undefined,
|
|
95
|
-
instance_type: p["instance_type"] as 0 | 1,
|
|
96
|
-
},
|
|
97
|
-
baseDir,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
if (!result.success) {
|
|
101
|
-
return {
|
|
102
|
-
content: [{ type: "text" as const, text: `注册失败:${result.error}` }],
|
|
103
|
-
details: result,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const successText = [
|
|
108
|
-
"注册成功 ✓",
|
|
109
|
-
`app_key: ${result.data?.app_key}`,
|
|
110
|
-
`claw_id: ${result.data?.claw_id}`,
|
|
111
|
-
"",
|
|
112
|
-
"InstaClaw channel 将在 10 秒内自动检测到凭证并建立 WebSocket 连接。",
|
|
113
|
-
].join("\n");
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
content: [{ type: "text" as const, text: successText }],
|
|
117
|
-
details: result,
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
};
|