@numa-tech/numa 1.20.2 → 1.20.4
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/README.md +13 -1
- package/dist/application-onboarding/schemas.d.ts +24 -0
- package/dist/application-onboarding/schemas.js +4 -0
- package/dist/application-onboarding/schemas.js.map +1 -1
- package/dist/application-onboarding/tui-model.d.ts +1 -0
- package/dist/application-onboarding/tui-model.js +10 -0
- package/dist/application-onboarding/tui-model.js.map +1 -1
- package/dist/application-onboarding/tui.js +1 -1
- package/dist/application-onboarding/tui.js.map +1 -1
- package/dist/authorization/application-client.d.ts +46 -5
- package/dist/authorization/application-client.js +21 -4
- package/dist/authorization/application-client.js.map +1 -1
- package/dist/authorization/application-commands.js +10 -3
- package/dist/authorization/application-commands.js.map +1 -1
- package/dist/authorization/application-schemas.d.ts +52 -6
- package/dist/authorization/application-schemas.js +25 -3
- package/dist/authorization/application-schemas.js.map +1 -1
- package/dist/business-issuer.js +8 -0
- package/dist/business-issuer.js.map +1 -1
- package/dist/cli.js +49 -31
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.js +9 -0
- package/dist/command-catalog.js.map +1 -1
- package/dist/kb/catalog.d.ts +2 -0
- package/dist/kb/catalog.js +14 -0
- package/dist/kb/catalog.js.map +1 -0
- package/dist/kb/client.d.ts +46 -0
- package/dist/kb/client.js +272 -0
- package/dist/kb/client.js.map +1 -0
- package/dist/kb/commands.d.ts +14 -0
- package/dist/kb/commands.js +121 -0
- package/dist/kb/commands.js.map +1 -0
- package/dist/kb/config.d.ts +15 -0
- package/dist/kb/config.js +76 -0
- package/dist/kb/config.js.map +1 -0
- package/dist/kb/errors.d.ts +9 -0
- package/dist/kb/errors.js +31 -0
- package/dist/kb/errors.js.map +1 -0
- package/dist/kb/transfers.d.ts +67 -0
- package/dist/kb/transfers.js +257 -0
- package/dist/kb/transfers.js.map +1 -0
- package/dist/kb/types.d.ts +81 -0
- package/dist/kb/types.js +2 -0
- package/dist/kb/types.js.map +1 -0
- package/dist/kb/upload-state.d.ts +20 -0
- package/dist/kb/upload-state.js +135 -0
- package/dist/kb/upload-state.js.map +1 -0
- package/dist/login-recovery.js +15 -1
- package/dist/login-recovery.js.map +1 -1
- package/dist/maintenance/modules.js +1 -1
- package/dist/maintenance/modules.js.map +1 -1
- package/dist/mcp/catalog.js +6 -1
- package/dist/mcp/catalog.js.map +1 -1
- package/dist/oss/file-operations.d.ts +8 -0
- package/dist/oss/file-operations.js +48 -6
- package/dist/oss/file-operations.js.map +1 -1
- package/dist/oss/signed-url-transfers.d.ts +41 -0
- package/dist/oss/signed-url-transfers.js +207 -0
- package/dist/oss/signed-url-transfers.js.map +1 -0
- package/dist/oss/transfer-pool.d.ts +2 -0
- package/dist/oss/transfer-pool.js +27 -0
- package/dist/oss/transfer-pool.js.map +1 -0
- package/dist/oss/transfer-worker.js +8 -17
- package/dist/oss/transfer-worker.js.map +1 -1
- package/dist/oss/web-page.js +48 -8
- package/dist/oss/web-page.js.map +1 -1
- package/dist/platform-profile.d.ts +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/tasks/commands.d.ts +9 -0
- package/dist/tasks/commands.js +60 -0
- package/dist/tasks/commands.js.map +1 -0
- package/dist/tasks/oss-query.d.ts +56 -0
- package/dist/tasks/oss-query.js +125 -0
- package/dist/tasks/oss-query.js.map +1 -0
- package/dist/tasks/runtime.d.ts +151 -0
- package/dist/tasks/runtime.js +71 -0
- package/dist/tasks/runtime.js.map +1 -0
- package/dist/tasks/tools.d.ts +3 -0
- package/dist/tasks/tools.js +16 -0
- package/dist/tasks/tools.js.map +1 -0
- package/dist/tasks/types.d.ts +14 -0
- package/dist/tasks/types.js +4 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/tasks/wecom-notify.d.ts +26 -0
- package/dist/tasks/wecom-notify.js +150 -0
- package/dist/tasks/wecom-notify.js.map +1 -0
- package/docs/agent-tasks.md +97 -0
- package/docs/application-default-groups.md +36 -0
- package/docs/design/kb-cli.md +94 -0
- package/docs/kb-access.md +85 -0
- package/package.json +12 -6
- package/scripts/export-kb-contract.py +158 -0
- package/skills/numa-ai-registry/SKILL.md +2 -2
- package/skills/numa-cli/SKILL.md +24 -9
- package/skills/numa-cli/agents/openai.yaml +2 -2
- package/skills/numa-cli/evals/evals.json +13 -1
- package/skills/numa-cli/numa-skill.json +1 -1
- package/skills/numa-cli/references/cli-bootstrap.md +8 -8
- package/skills/numa-cli/references/cli-mcp.md +28 -20
- package/skills/numa-cli/references/pipeline-release.md +9 -9
- package/skills/numa-cli/references/skills-command-contract.md +40 -40
- package/skills/numa-cli/references/skills-updates.md +13 -13
- package/skills/numa-cli/references/skills-workflows.md +4 -4
- package/skills/numa-create-application/SKILL.md +1 -1
- package/skills/numa-create-application/numa-skill.json +2 -2
- package/skills/numa-create-application/references/cli-bootstrap.md +3 -3
- package/skills/numa-create-application/references/numa-cli.md +16 -16
- package/skills/numa-jenkins-deployment/SKILL.md +8 -8
- package/skills/numa-jenkins-deployment/numa-skill.json +2 -2
- package/skills/numa-jenkins-deployment/references/cli-bootstrap.md +3 -3
- package/skills/numa-jenkins-deployment/references/cli-contract.md +7 -7
- package/skills/numa-jenkins-deployment/references/diagnostics.md +2 -2
- package/skills/numa-local-flux-deploy/SKILL.md +1 -1
- package/skills/numa-local-flux-deploy/numa-skill.json +2 -2
- package/skills/numa-local-flux-deploy/references/cli-bootstrap.md +3 -3
- package/skills/numa-nacos/SKILL.md +4 -4
- package/skills/numa-nacos/numa-skill.json +2 -2
- package/skills/numa-nacos/references/cli-bootstrap.md +3 -3
- package/skills/numa-nacos/references/command-contract.md +17 -17
- package/skills/numa-notion/SKILL.md +4 -4
- package/skills/numa-notion/numa-skill.json +2 -2
- package/skills/numa-notion/references/agents-automation.md +2 -2
- package/skills/numa-notion/references/cli-bootstrap.md +3 -3
- package/skills/numa-notion/references/cli.md +17 -17
- package/skills/numa-oss-access/SKILL.md +27 -81
- package/skills/numa-oss-access/agents/openai.yaml +2 -2
- package/skills/numa-oss-access/evals/evals.json +12 -0
- package/skills/numa-oss-access/numa-skill.json +2 -2
- package/skills/numa-oss-access/references/cli-bootstrap.md +5 -5
- package/skills/numa-oss-access/references/object-operations.md +95 -0
- package/skills/numa-oss-access/references/search-and-mcp.md +12 -11
- package/skills/numa-wecom/SKILL.md +27 -62
- package/skills/numa-wecom/agents/openai.yaml +2 -2
- package/skills/numa-wecom/evals/evals.json +25 -0
- package/skills/numa-wecom/numa-skill.json +2 -2
- package/skills/numa-wecom/references/cli-bootstrap.md +5 -5
- package/skills/numa-wecom/references/legacy-operations.md +71 -0
- package/skills/numa-wecom/references/machine-auth.md +7 -7
- package/skills/numa-wecom/references/mcp.md +9 -8
- package/src/kb/openapi-contract.json +1432 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import { OssClient } from "../oss/client.js";
|
|
4
|
+
import { OssError, sanitizeOssOutput } from "../oss/errors.js";
|
|
5
|
+
import { SEARCH_FIELDS, projectEntries, searchObjects, validateSearchOptions } from "../oss/search.js";
|
|
6
|
+
import { OssTransferClient } from "../oss/transfers.js";
|
|
7
|
+
const path = z.string().max(1024).refine(value => value === value.trim()
|
|
8
|
+
&& !/[\\\u0000-\u001f\u007f]/u.test(value)
|
|
9
|
+
&& !value.split("/").some(part => part === "." || part === ".."), "Invalid OSS path");
|
|
10
|
+
export const ossQuerySchema = z.object({
|
|
11
|
+
grant_id: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
12
|
+
bucket: z.string().min(1).max(63).regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/u).optional()
|
|
13
|
+
.describe("Exact bucket name; required with prefix when grant_id is omitted"),
|
|
14
|
+
prefix: path.optional().describe("Exact requested prefix; an explicit empty string requests the bucket root"),
|
|
15
|
+
ttl: z.number().int().min(900).max(3600).optional(),
|
|
16
|
+
marker: path.min(1).optional(), delimiter: z.literal("/").optional(), directories_only: z.boolean().optional(),
|
|
17
|
+
contains: z.string().min(1).max(1024).optional(), suffix: z.string().min(1).max(1024).optional(), ignore_case: z.boolean().optional(),
|
|
18
|
+
min_size: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
19
|
+
max_size: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
20
|
+
modified_after: z.string().optional(), modified_before: z.string().optional(),
|
|
21
|
+
created_time_key: z.string().optional(), created_after: z.string().optional(), created_before: z.string().optional(),
|
|
22
|
+
meta: z.array(z.string().max(2048)).max(20).optional(), content_type: z.string().optional(),
|
|
23
|
+
sort: z.enum(["key", "size", "modified", "created"]).default("key"), order: z.enum(["asc", "desc"]).default("asc"),
|
|
24
|
+
limit: z.number().int().min(1).max(1000).default(100), scan_limit: z.number().int().min(1).max(100000).default(1000),
|
|
25
|
+
fields: z.array(z.enum(SEARCH_FIELDS)).min(1).optional()
|
|
26
|
+
}).strict();
|
|
27
|
+
function covered(scope, root, prefix) {
|
|
28
|
+
const kind = scope?.trim().toUpperCase().replace(/^OSS_/u, "");
|
|
29
|
+
const normalized = (root ?? "").trim().replace(/^\/+|\/+$/gu, "");
|
|
30
|
+
if (!["BUCKET", "PREFIX"].includes(kind ?? "") || kind === "PREFIX" && !normalized
|
|
31
|
+
|| !path.safeParse(normalized).success)
|
|
32
|
+
return false;
|
|
33
|
+
return !normalized || prefix === normalized || prefix.startsWith(`${normalized}/`);
|
|
34
|
+
}
|
|
35
|
+
// Grant schemas deliberately preserve backend extensions; never return them to the agent.
|
|
36
|
+
function candidate(grant) {
|
|
37
|
+
return { grant_id: grant.grantId, bucket: grant.bucketName, prefix: grant.objectPrefix ?? "",
|
|
38
|
+
scope_type: grant.scopeType, permission_level: grant.permissionLevel };
|
|
39
|
+
}
|
|
40
|
+
/** Only selection hints; the issued session and OSS remain the authorization boundary. */
|
|
41
|
+
function supportsQuery(grant, needsHead) {
|
|
42
|
+
// Nullable Grant metadata represents the absence of explicit policy actions.
|
|
43
|
+
// Session schemas use undefined for that same legacy permission-level fallback.
|
|
44
|
+
const actions = grant.actions ?? undefined;
|
|
45
|
+
const effect = grant.effect ?? undefined;
|
|
46
|
+
if (actions !== undefined || effect !== undefined) {
|
|
47
|
+
const required = needsHead ? ["oss:ListObjects", "oss:GetObject"] : ["oss:ListObjects"];
|
|
48
|
+
return effect === "Allow" && Array.isArray(actions)
|
|
49
|
+
&& required.every(action => actions.includes(action) || actions.includes("oss:*"));
|
|
50
|
+
}
|
|
51
|
+
return ["ADMIN", "READ_ONLY", "READ_WRITE", "READ_WRITE_NO_DELETE"].includes(grant.permissionLevel?.trim().toUpperCase() ?? "");
|
|
52
|
+
}
|
|
53
|
+
function safe(value) {
|
|
54
|
+
const redacted = sanitizeOssOutput(value);
|
|
55
|
+
const stripUrls = (item) => {
|
|
56
|
+
if (typeof item === "string")
|
|
57
|
+
return item.replace(/https?:\/\/[^\s<>"']+/giu, "[REDACTED_URL]");
|
|
58
|
+
if (Array.isArray(item))
|
|
59
|
+
return item.map(stripUrls);
|
|
60
|
+
if (item && typeof item === "object")
|
|
61
|
+
return Object.fromEntries(Object.entries(item).map(([key, data]) => [key, stripUrls(data)]));
|
|
62
|
+
return item;
|
|
63
|
+
};
|
|
64
|
+
return stripUrls(redacted);
|
|
65
|
+
}
|
|
66
|
+
/** One bounded read workflow; a denied or ambiguous Grant never triggers a fallback. */
|
|
67
|
+
export async function runOssQuery(input, dependencies = {}) {
|
|
68
|
+
const task = "oss.query";
|
|
69
|
+
const parsed = ossQuerySchema.safeParse(input);
|
|
70
|
+
if (!parsed.success)
|
|
71
|
+
return { status: "needs_input", task,
|
|
72
|
+
error: { code: "oss_input_invalid", message: "Supply valid OSS query parameters." },
|
|
73
|
+
missing: [...new Set(parsed.error.issues.map(issue => issue.path.join(".")).filter(Boolean))] };
|
|
74
|
+
const query = parsed.data;
|
|
75
|
+
if (query.grant_id === undefined && (query.bucket === undefined || query.prefix === undefined)) {
|
|
76
|
+
return { status: "needs_input", task, missing: [query.bucket === undefined ? "bucket" : "", query.prefix === undefined ? "prefix" : ""].filter(Boolean),
|
|
77
|
+
error: { code: "oss_target_required", message: "Specify grant_id, or both an exact bucket and prefix. Use an explicit empty prefix for the bucket root." } };
|
|
78
|
+
}
|
|
79
|
+
const options = { marker: query.marker, delimiter: query.delimiter, directoriesOnly: query.directories_only,
|
|
80
|
+
contains: query.contains, suffix: query.suffix, ignoreCase: query.ignore_case,
|
|
81
|
+
minSize: query.min_size, maxSize: query.max_size, modifiedAfter: query.modified_after, modifiedBefore: query.modified_before,
|
|
82
|
+
createdTimeKey: query.created_time_key, createdAfter: query.created_after, createdBefore: query.created_before,
|
|
83
|
+
meta: query.meta, contentType: query.content_type, sort: query.sort, order: query.order,
|
|
84
|
+
limit: query.limit, scanLimit: query.scan_limit, fields: query.fields?.join(",") };
|
|
85
|
+
try {
|
|
86
|
+
const validated = validateSearchOptions(options);
|
|
87
|
+
await dependencies.beforeExecute?.();
|
|
88
|
+
const client = dependencies.clientFactory?.() ?? new OssClient(loadConfig("oss"));
|
|
89
|
+
let grantId = query.grant_id;
|
|
90
|
+
if (grantId === undefined) {
|
|
91
|
+
const available = await client.listGrants();
|
|
92
|
+
// One platform request, with a hard ceiling on selection and candidate output.
|
|
93
|
+
if (available.grants.length > 10000)
|
|
94
|
+
return { status: "needs_input", task, missing: ["grant_id"],
|
|
95
|
+
error: { code: "oss_grant_limit", message: "Too many Grants for automatic selection; provide the exact grant_id." } };
|
|
96
|
+
const matches = available.grants.filter(grant => grant.status === "ACTIVE" && grant.cloudPolicySynced
|
|
97
|
+
&& grant.roleName && grant.bucketName === query.bucket && supportsQuery(grant, validated.needsHead)
|
|
98
|
+
&& covered(grant.scopeType, grant.objectPrefix, query.prefix));
|
|
99
|
+
if (!matches.length)
|
|
100
|
+
return { status: "blocked", task,
|
|
101
|
+
error: { code: "oss_grant_unavailable", message: "No enabled, synchronized Grant covers the requested bucket and prefix." } };
|
|
102
|
+
if (matches.length > 1)
|
|
103
|
+
return { status: "needs_input", task, missing: ["grant_id"],
|
|
104
|
+
candidates: safe(matches.slice(0, 100).map(candidate)),
|
|
105
|
+
error: { code: "oss_grant_ambiguous", message: "Multiple Grants cover this target; select an exact grant_id. At most 100 candidates are shown." } };
|
|
106
|
+
grantId = matches[0].grantId;
|
|
107
|
+
}
|
|
108
|
+
const session = await client.issueSession(grantId, query.ttl);
|
|
109
|
+
if (session.grantId !== grantId || query.bucket !== undefined && session.bucketName !== query.bucket
|
|
110
|
+
|| query.prefix !== undefined && !covered(session.scopeType, session.objectPrefix, query.prefix)) {
|
|
111
|
+
return { status: "blocked", task, error: { code: "oss_target_mismatch", message: "The issued session does not cover the exact requested target." } };
|
|
112
|
+
}
|
|
113
|
+
const transfer = dependencies.transferFactory?.() ?? new OssTransferClient();
|
|
114
|
+
const result = await searchObjects(transfer, session, query.prefix, options);
|
|
115
|
+
return { status: "succeeded", task,
|
|
116
|
+
data: safe({ grant_id: grantId, bucket: session.bucketName, ...result, objects: projectEntries(result.objects, validated.fields) }) };
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (!(error instanceof OssError))
|
|
120
|
+
throw error;
|
|
121
|
+
return { status: error.code === "oss_input_invalid" ? "needs_input" : "blocked", task,
|
|
122
|
+
error: { code: error.code, message: safe(error.message) } };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=oss-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oss-query.js","sourceRoot":"","sources":["../../src/tasks/oss-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type AuthConfig } from "../config.js";
|
|
3
|
+
import { type WecomNotifyDependencies } from "./wecom-notify.js";
|
|
4
|
+
import { type OssQueryDependencies } from "./oss-query.js";
|
|
5
|
+
import type { TaskResult } from "./types.js";
|
|
6
|
+
export declare const TASKS: readonly [{
|
|
7
|
+
readonly name: "wecom.notify";
|
|
8
|
+
readonly tool: "numa_wecom_notify";
|
|
9
|
+
readonly module: "wecom";
|
|
10
|
+
readonly readOnly: false;
|
|
11
|
+
readonly description: "一次完成企微通道检查、精确收件人解析、已授权通知发送和未知结果查询。";
|
|
12
|
+
readonly schema: z.ZodObject<{
|
|
13
|
+
recipient_email: z.ZodOptional<z.ZodString>;
|
|
14
|
+
email_type: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
|
|
15
|
+
recipient_user_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
content: z.ZodOptional<z.ZodString>;
|
|
17
|
+
message_type: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
markdown: "markdown";
|
|
19
|
+
text: "text";
|
|
20
|
+
}>>;
|
|
21
|
+
safe: z.ZodDefault<z.ZodBoolean>;
|
|
22
|
+
request_id: z.ZodOptional<z.ZodString>;
|
|
23
|
+
confirmed: z.ZodDefault<z.ZodBoolean>;
|
|
24
|
+
}, z.core.$strict>;
|
|
25
|
+
}, {
|
|
26
|
+
readonly name: "oss.query";
|
|
27
|
+
readonly tool: "numa_oss_query";
|
|
28
|
+
readonly module: "oss";
|
|
29
|
+
readonly readOnly: true;
|
|
30
|
+
readonly description: "一次完成精确目标的唯一 Grant 选择和有界 OSS 检索;歧义返回候选。";
|
|
31
|
+
readonly schema: z.ZodObject<{
|
|
32
|
+
grant_id: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
bucket: z.ZodOptional<z.ZodString>;
|
|
34
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
35
|
+
ttl: z.ZodOptional<z.ZodNumber>;
|
|
36
|
+
marker: z.ZodOptional<z.ZodString>;
|
|
37
|
+
delimiter: z.ZodOptional<z.ZodLiteral<"/">>;
|
|
38
|
+
directories_only: z.ZodOptional<z.ZodBoolean>;
|
|
39
|
+
contains: z.ZodOptional<z.ZodString>;
|
|
40
|
+
suffix: z.ZodOptional<z.ZodString>;
|
|
41
|
+
ignore_case: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
min_size: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
max_size: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
modified_after: z.ZodOptional<z.ZodString>;
|
|
45
|
+
modified_before: z.ZodOptional<z.ZodString>;
|
|
46
|
+
created_time_key: z.ZodOptional<z.ZodString>;
|
|
47
|
+
created_after: z.ZodOptional<z.ZodString>;
|
|
48
|
+
created_before: z.ZodOptional<z.ZodString>;
|
|
49
|
+
meta: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
content_type: z.ZodOptional<z.ZodString>;
|
|
51
|
+
sort: z.ZodDefault<z.ZodEnum<{
|
|
52
|
+
created: "created";
|
|
53
|
+
key: "key";
|
|
54
|
+
modified: "modified";
|
|
55
|
+
size: "size";
|
|
56
|
+
}>>;
|
|
57
|
+
order: z.ZodDefault<z.ZodEnum<{
|
|
58
|
+
asc: "asc";
|
|
59
|
+
desc: "desc";
|
|
60
|
+
}>>;
|
|
61
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
62
|
+
scan_limit: z.ZodDefault<z.ZodNumber>;
|
|
63
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
64
|
+
contentType: "contentType";
|
|
65
|
+
createdAt: "createdAt";
|
|
66
|
+
etag: "etag";
|
|
67
|
+
key: "key";
|
|
68
|
+
kind: "kind";
|
|
69
|
+
lastModified: "lastModified";
|
|
70
|
+
metadata: "metadata";
|
|
71
|
+
sizeBytes: "sizeBytes";
|
|
72
|
+
storageClass: "storageClass";
|
|
73
|
+
type: "type";
|
|
74
|
+
}>>>;
|
|
75
|
+
}, z.core.$strict>;
|
|
76
|
+
}];
|
|
77
|
+
export interface TaskDependencies {
|
|
78
|
+
wecom?: WecomNotifyDependencies;
|
|
79
|
+
oss?: OssQueryDependencies;
|
|
80
|
+
/** Injection points keep tests offline; production always validates the selected profile. */
|
|
81
|
+
initializeProfile?: () => Promise<void>;
|
|
82
|
+
config?: (task: string) => AuthConfig;
|
|
83
|
+
}
|
|
84
|
+
export declare function inspectTasks(name?: string): {
|
|
85
|
+
name: "oss.query" | "wecom.notify";
|
|
86
|
+
tool: "numa_oss_query" | "numa_wecom_notify";
|
|
87
|
+
module: "oss" | "wecom";
|
|
88
|
+
description: "一次完成企微通道检查、精确收件人解析、已授权通知发送和未知结果查询。" | "一次完成精确目标的唯一 Grant 选择和有界 OSS 检索;歧义返回候选。";
|
|
89
|
+
read_only: boolean;
|
|
90
|
+
input_schema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
|
|
91
|
+
recipient_email: z.ZodOptional<z.ZodString>;
|
|
92
|
+
email_type: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
|
|
93
|
+
recipient_user_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
94
|
+
content: z.ZodOptional<z.ZodString>;
|
|
95
|
+
message_type: z.ZodDefault<z.ZodEnum<{
|
|
96
|
+
markdown: "markdown";
|
|
97
|
+
text: "text";
|
|
98
|
+
}>>;
|
|
99
|
+
safe: z.ZodDefault<z.ZodBoolean>;
|
|
100
|
+
request_id: z.ZodOptional<z.ZodString>;
|
|
101
|
+
confirmed: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
}, z.core.$strict> | z.ZodObject<{
|
|
103
|
+
grant_id: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
bucket: z.ZodOptional<z.ZodString>;
|
|
105
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
106
|
+
ttl: z.ZodOptional<z.ZodNumber>;
|
|
107
|
+
marker: z.ZodOptional<z.ZodString>;
|
|
108
|
+
delimiter: z.ZodOptional<z.ZodLiteral<"/">>;
|
|
109
|
+
directories_only: z.ZodOptional<z.ZodBoolean>;
|
|
110
|
+
contains: z.ZodOptional<z.ZodString>;
|
|
111
|
+
suffix: z.ZodOptional<z.ZodString>;
|
|
112
|
+
ignore_case: z.ZodOptional<z.ZodBoolean>;
|
|
113
|
+
min_size: z.ZodOptional<z.ZodNumber>;
|
|
114
|
+
max_size: z.ZodOptional<z.ZodNumber>;
|
|
115
|
+
modified_after: z.ZodOptional<z.ZodString>;
|
|
116
|
+
modified_before: z.ZodOptional<z.ZodString>;
|
|
117
|
+
created_time_key: z.ZodOptional<z.ZodString>;
|
|
118
|
+
created_after: z.ZodOptional<z.ZodString>;
|
|
119
|
+
created_before: z.ZodOptional<z.ZodString>;
|
|
120
|
+
meta: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
121
|
+
content_type: z.ZodOptional<z.ZodString>;
|
|
122
|
+
sort: z.ZodDefault<z.ZodEnum<{
|
|
123
|
+
created: "created";
|
|
124
|
+
key: "key";
|
|
125
|
+
modified: "modified";
|
|
126
|
+
size: "size";
|
|
127
|
+
}>>;
|
|
128
|
+
order: z.ZodDefault<z.ZodEnum<{
|
|
129
|
+
asc: "asc";
|
|
130
|
+
desc: "desc";
|
|
131
|
+
}>>;
|
|
132
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
133
|
+
scan_limit: z.ZodDefault<z.ZodNumber>;
|
|
134
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
135
|
+
contentType: "contentType";
|
|
136
|
+
createdAt: "createdAt";
|
|
137
|
+
etag: "etag";
|
|
138
|
+
key: "key";
|
|
139
|
+
kind: "kind";
|
|
140
|
+
lastModified: "lastModified";
|
|
141
|
+
metadata: "metadata";
|
|
142
|
+
sizeBytes: "sizeBytes";
|
|
143
|
+
storageClass: "storageClass";
|
|
144
|
+
type: "type";
|
|
145
|
+
}>>>;
|
|
146
|
+
}, z.core.$strict>>;
|
|
147
|
+
result_statuses: string[];
|
|
148
|
+
}[];
|
|
149
|
+
/** Validate configuration only. Clients obtain/reuse tokens and the server enforces authorization. */
|
|
150
|
+
export declare function validateTaskIdentity(config: AuthConfig): void;
|
|
151
|
+
export declare function runTask(name: string, input: unknown, dependencies?: TaskDependencies): Promise<TaskResult>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import { currentPlatformProfile, initializePlatformProfile } from "../platform-profile.js";
|
|
4
|
+
import { runWecomNotify, wecomNotifySchema } from "./wecom-notify.js";
|
|
5
|
+
import { runOssQuery, ossQuerySchema } from "./oss-query.js";
|
|
6
|
+
export const TASKS = [
|
|
7
|
+
{ name: "wecom.notify", tool: "numa_wecom_notify", module: "wecom", readOnly: false,
|
|
8
|
+
description: "一次完成企微通道检查、精确收件人解析、已授权通知发送和未知结果查询。", schema: wecomNotifySchema },
|
|
9
|
+
{ name: "oss.query", tool: "numa_oss_query", module: "oss", readOnly: true,
|
|
10
|
+
description: "一次完成精确目标的唯一 Grant 选择和有界 OSS 检索;歧义返回候选。", schema: ossQuerySchema },
|
|
11
|
+
];
|
|
12
|
+
export function inspectTasks(name) {
|
|
13
|
+
return TASKS.filter(task => name === undefined || task.name === name).map(task => ({
|
|
14
|
+
name: task.name, tool: task.tool, module: task.module,
|
|
15
|
+
description: task.description, read_only: task.readOnly,
|
|
16
|
+
input_schema: z.toJSONSchema(task.schema, { io: "input" }),
|
|
17
|
+
result_statuses: ["succeeded", "needs_input", "blocked", "pending"],
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
/** Validate configuration only. Clients obtain/reuse tokens and the server enforces authorization. */
|
|
21
|
+
export function validateTaskIdentity(config) {
|
|
22
|
+
if (!config.backendBaseUrl || !config.discoveryUrl || !config.clientId?.trim())
|
|
23
|
+
throw Object.assign(new Error(), { code: "TASK_CONFIGURATION_REQUIRED" });
|
|
24
|
+
if (config.authenticationMode === "client_credentials") {
|
|
25
|
+
if (config.clientId === "mcp-client" || Boolean(config.clientSecret) === Boolean(config.clientSecretFile))
|
|
26
|
+
throw Object.assign(new Error(), { code: "TASK_MACHINE_IDENTITY_REQUIRED" });
|
|
27
|
+
}
|
|
28
|
+
else if (config.clientSecret || config.clientSecretFile) {
|
|
29
|
+
// An explicit browser identity must not accidentally consume machine credentials.
|
|
30
|
+
throw Object.assign(new Error(), { code: "TASK_IDENTITY_CONFLICT" });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const configurationMessages = {
|
|
34
|
+
TASK_CONFIGURATION_REQUIRED: "Configure the selected platform API, issuer and client before running this task.",
|
|
35
|
+
TASK_MACHINE_IDENTITY_REQUIRED: "Machine mode requires a dedicated client and exactly one Secret source in this process environment. No browser fallback was attempted.",
|
|
36
|
+
TASK_IDENTITY_CONFLICT: "Browser mode and machine credentials conflict. Correct this process configuration; identity was not changed.",
|
|
37
|
+
};
|
|
38
|
+
export async function runTask(name, input, dependencies = {}) {
|
|
39
|
+
const task = TASKS.find(item => item.name === name);
|
|
40
|
+
if (!task)
|
|
41
|
+
return { task: name, status: "blocked", error: { code: "TASK_UNKNOWN", message: "Unknown task. Use task inspect to list supported tasks." } };
|
|
42
|
+
// Validate shape before loading a profile, obtaining credentials, or making any network requests.
|
|
43
|
+
const parsed = task.schema.safeParse(input);
|
|
44
|
+
if (!parsed.success)
|
|
45
|
+
return { task: name, status: "needs_input",
|
|
46
|
+
missing: [...new Set(parsed.error.issues.map(issue => issue.path.join(".") || "input"))],
|
|
47
|
+
error: { code: "TASK_INPUT_INVALID", message: "Task input does not match its schema. Correct the listed fields." } };
|
|
48
|
+
try {
|
|
49
|
+
const beforeExecute = async () => {
|
|
50
|
+
if (dependencies.initializeProfile)
|
|
51
|
+
await dependencies.initializeProfile();
|
|
52
|
+
else if (!currentPlatformProfile())
|
|
53
|
+
await initializePlatformProfile();
|
|
54
|
+
const config = dependencies.config?.(name) ?? loadConfig(name === "oss.query" ? "oss" : "platform");
|
|
55
|
+
validateTaskIdentity(config);
|
|
56
|
+
};
|
|
57
|
+
const result = name === "wecom.notify"
|
|
58
|
+
? await runWecomNotify(parsed.data, { ...dependencies.wecom, beforeExecute })
|
|
59
|
+
: await runOssQuery(parsed.data, { ...dependencies.oss, beforeExecute });
|
|
60
|
+
// Each task owns output projection/redaction. Do not rewrite opaque recovery IDs here.
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// Never expose provider exceptions, request objects, credentials, or arbitrary response bodies.
|
|
65
|
+
const rawCode = error && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
66
|
+
const code = typeof rawCode === "string" && /^[A-Za-z][A-Za-z0-9_]{0,79}$/u.test(rawCode) ? rawCode : "TASK_CONFIGURATION_OR_AUTH_FAILED";
|
|
67
|
+
return { task: name, status: "blocked", error: { code,
|
|
68
|
+
message: configurationMessages[code] ?? "Task initialization failed. Check the selected profile and process authentication configuration; no alternate identity was used." } };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/tasks/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TASKS, runTask } from "./runtime.js";
|
|
2
|
+
export function registerTaskTools(server, modules, dependencies = {}) {
|
|
3
|
+
for (const task of TASKS) {
|
|
4
|
+
if (!modules.has(task.module))
|
|
5
|
+
continue;
|
|
6
|
+
server.registerTool(task.tool, {
|
|
7
|
+
description: `${task.description} Call this task directly; configuration/authentication and required lookups run internally, without separate auth/catalog/capability calls. Uses this MCP process identity and environment. Returns succeeded, needs_input, blocked or pending. ${task.readOnly ? "Read-only bounded query; ambiguous Grants require user selection." : "SIDE EFFECT: requires user-approved exact recipients and content, confirmed=true and a stable request_id. ACCEPTED is not delivery. pending must be recovered with numa_wecom_status using the same request_id; never resend."}`,
|
|
8
|
+
inputSchema: task.schema,
|
|
9
|
+
annotations: { readOnlyHint: task.readOnly, destructiveHint: false, idempotentHint: task.readOnly, openWorldHint: true },
|
|
10
|
+
}, async (input) => {
|
|
11
|
+
const result = await runTask(task.name, input, dependencies);
|
|
12
|
+
return { isError: result.status === "blocked", content: [{ type: "text", text: JSON.stringify(result) }], structuredContent: { ...result } };
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/tasks/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAyB,MAAM,cAAc,CAAC;AAErE,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,OAA4B,EAAE,YAAY,GAAqB,EAAE;IACpH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,SAAS;QACxC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE;YAC7B,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,mPAAmP,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,mEAAmE,CAAC,CAAC,CAAC,+NAA+N,EAAE;YAC1kB,WAAW,EAAE,IAAI,CAAC,MAAM;YACxB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE;SACzH,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE;YAC1B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;YAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;QACxJ,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A task result is actionable without another discovery/preflight model turn. */
|
|
2
|
+
export interface TaskResult {
|
|
3
|
+
status: "succeeded" | "needs_input" | "blocked" | "pending";
|
|
4
|
+
task: string;
|
|
5
|
+
data?: unknown;
|
|
6
|
+
error?: {
|
|
7
|
+
code: string;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
missing?: string[];
|
|
11
|
+
candidates?: unknown[];
|
|
12
|
+
request_id?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function taskExitCode(result: TaskResult): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { WecomClient } from "../wecom/client.js";
|
|
3
|
+
import type { TaskResult } from "./types.js";
|
|
4
|
+
/** Optional fields let both entry points return actionable needs_input results. */
|
|
5
|
+
export declare const wecomNotifySchema: z.ZodObject<{
|
|
6
|
+
recipient_email: z.ZodOptional<z.ZodString>;
|
|
7
|
+
email_type: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
|
|
8
|
+
recipient_user_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
9
|
+
content: z.ZodOptional<z.ZodString>;
|
|
10
|
+
message_type: z.ZodDefault<z.ZodEnum<{
|
|
11
|
+
markdown: "markdown";
|
|
12
|
+
text: "text";
|
|
13
|
+
}>>;
|
|
14
|
+
safe: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
+
request_id: z.ZodOptional<z.ZodString>;
|
|
16
|
+
confirmed: z.ZodDefault<z.ZodBoolean>;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
type NotifyClient = Pick<WecomClient, "capabilities" | "recipientByEmail" | "send" | "statusByRequest">;
|
|
19
|
+
export interface WecomNotifyDependencies {
|
|
20
|
+
client?: NotifyClient;
|
|
21
|
+
clientFactory?: () => NotifyClient;
|
|
22
|
+
beforeExecute?: () => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
/** Deterministic, bounded notification workflow shared by CLI and MCP. */
|
|
25
|
+
export declare function runWecomNotify(input: unknown, dependencies?: WecomNotifyDependencies): Promise<TaskResult>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import { WecomClient } from "../wecom/client.js";
|
|
4
|
+
import { WecomError } from "../wecom/errors.js";
|
|
5
|
+
import { EmailSchema, EmailTypeSchema, MessageTypeSchema, RequestIdSchema, SendMessageSchema, UserIdSchema } from "../wecom/schemas.js";
|
|
6
|
+
/** Optional fields let both entry points return actionable needs_input results. */
|
|
7
|
+
export const wecomNotifySchema = z.object({
|
|
8
|
+
recipient_email: EmailSchema.optional(),
|
|
9
|
+
email_type: EmailTypeSchema.optional(),
|
|
10
|
+
recipient_user_ids: z.array(UserIdSchema).min(1).max(100).refine(ids => new Set(ids).size === ids.length).optional(),
|
|
11
|
+
content: z.string().min(1).refine(value => value.trim().length > 0).optional(),
|
|
12
|
+
message_type: MessageTypeSchema.default("text"),
|
|
13
|
+
safe: z.boolean().default(false),
|
|
14
|
+
request_id: RequestIdSchema.optional(),
|
|
15
|
+
confirmed: z.boolean().default(false).describe("True only when the user has authorized these exact recipients and content; existing authorization is sufficient")
|
|
16
|
+
}).strict();
|
|
17
|
+
const task = "wecom.notify";
|
|
18
|
+
function blocked(code, message, requestId) {
|
|
19
|
+
return { task, status: "blocked", error: { code, message }, ...(requestId ? { request_id: requestId } : {}) };
|
|
20
|
+
}
|
|
21
|
+
function pending(requestId) {
|
|
22
|
+
return { task, status: "pending", request_id: requestId, error: {
|
|
23
|
+
code: "WECOM_RESULT_PENDING",
|
|
24
|
+
message: "Send acceptance is not yet known. Query status using this request_id; do not resend or generate a new request ID."
|
|
25
|
+
} };
|
|
26
|
+
}
|
|
27
|
+
function safeError(error, requestId) {
|
|
28
|
+
const status = error instanceof WecomError ? error.status : undefined;
|
|
29
|
+
return blocked(status === 401 ? "WECOM_AUTHENTICATION_REQUIRED" : status === 403 ? "WECOM_PERMISSION_DENIED" : "WECOM_TASK_BLOCKED", status === 401 || status === 403
|
|
30
|
+
? "The configured identity cannot complete this operation. Correct its authentication or grants; do not switch identities."
|
|
31
|
+
: "WeCom operation failed before acceptance. Check channel configuration, exact recipient and email type, and the configured identity. No automatic retry was made.", requestId);
|
|
32
|
+
}
|
|
33
|
+
function receiptResult(receipt, requestId) {
|
|
34
|
+
// Never report another request's receipt as acceptance of this one.
|
|
35
|
+
if (receipt.requestId !== requestId)
|
|
36
|
+
return pending(requestId);
|
|
37
|
+
const data = { message_id: receipt.id, receipt_status: receipt.status,
|
|
38
|
+
recipient_user_ids: receipt.recipientUserIds, invalid_user_ids: receipt.invalidUserIds };
|
|
39
|
+
if (receipt.status === "ACCEPTED")
|
|
40
|
+
return { task, status: "succeeded", request_id: requestId,
|
|
41
|
+
data: { ...data, message: "Accepted by the WeCom API; delivery and read status are not confirmed." } };
|
|
42
|
+
if (receipt.status === "SENDING" || receipt.status === "UNKNOWN")
|
|
43
|
+
return { ...pending(requestId), data };
|
|
44
|
+
return { ...blocked(receipt.status === "PARTIAL" ? "WECOM_PARTIAL_ACCEPTANCE" : "WECOM_SEND_FAILED", receipt.status === "PARTIAL"
|
|
45
|
+
? "The API accepted only some recipients. Review the receipt; do not resend to the full recipient list."
|
|
46
|
+
: "The API reported a failed send. Review the receipt before taking further action.", requestId), data };
|
|
47
|
+
}
|
|
48
|
+
async function recover(client, requestId) {
|
|
49
|
+
try {
|
|
50
|
+
return receiptResult(await client.statusByRequest(requestId), requestId);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (error instanceof WecomError && (error.status === 401 || error.status === 403)) {
|
|
54
|
+
return { ...safeError(error, requestId), data: { send_outcome: "unknown", message: "The send outcome remains unknown. Restore access and query this request_id; do not resend." } };
|
|
55
|
+
}
|
|
56
|
+
// A missing ledger entry, unavailable platform, or invalid receipt is not proof of no send.
|
|
57
|
+
return pending(requestId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Deterministic, bounded notification workflow shared by CLI and MCP. */
|
|
61
|
+
export async function runWecomNotify(input, dependencies = {}) {
|
|
62
|
+
const parsed = wecomNotifySchema.safeParse(input);
|
|
63
|
+
if (!parsed.success)
|
|
64
|
+
return { task, status: "needs_input", missing: [...new Set(parsed.error.issues
|
|
65
|
+
.map(issue => typeof issue.path[0] === "string" ? issue.path[0] : "input"))],
|
|
66
|
+
error: { code: "WECOM_INPUT_INVALID", message: "Supply valid notification fields, exact recipients, and a stable request_id of 8-128 safe ASCII characters." } };
|
|
67
|
+
const value = parsed.data;
|
|
68
|
+
const missing = [];
|
|
69
|
+
if (!value.content)
|
|
70
|
+
missing.push("content");
|
|
71
|
+
if (!value.request_id)
|
|
72
|
+
missing.push("request_id");
|
|
73
|
+
if (!value.confirmed)
|
|
74
|
+
missing.push("confirmed");
|
|
75
|
+
if (!value.recipient_email && !value.recipient_user_ids)
|
|
76
|
+
missing.push("recipient_email or recipient_user_ids");
|
|
77
|
+
if (value.recipient_email && value.email_type === undefined)
|
|
78
|
+
missing.push("email_type");
|
|
79
|
+
if (missing.length)
|
|
80
|
+
return { task, status: "needs_input", missing, error: { code: "WECOM_INPUT_REQUIRED",
|
|
81
|
+
message: "Provide the missing fields. confirmed=true represents existing user authorization for these exact recipients and content; ask only if authorization is absent." } };
|
|
82
|
+
const requestId = value.request_id;
|
|
83
|
+
const body = SendMessageSchema.safeParse({
|
|
84
|
+
...(value.recipient_email ? { recipientEmail: value.recipient_email, emailType: value.email_type } : {}),
|
|
85
|
+
...(value.recipient_user_ids ? { recipientUserIds: value.recipient_user_ids } : {}),
|
|
86
|
+
// An email_type without email is invalid even when userid recipients were supplied.
|
|
87
|
+
...(!value.recipient_email && value.email_type !== undefined ? { emailType: value.email_type } : {}),
|
|
88
|
+
messageType: value.message_type, content: value.content, safe: value.safe
|
|
89
|
+
});
|
|
90
|
+
if (!body.success) {
|
|
91
|
+
const names = { recipientUserIds: "recipient_user_ids", recipientEmail: "recipient_email", emailType: "email_type", messageType: "message_type" };
|
|
92
|
+
const fields = body.error.issues.map(issue => {
|
|
93
|
+
const field = typeof issue.path[0] === "string" ? issue.path[0] : "input";
|
|
94
|
+
// The shared DTO uses the recipientUserIds path for all recipient-mode conflicts.
|
|
95
|
+
if (field === "recipientUserIds" && value.email_type !== undefined && !value.recipient_email)
|
|
96
|
+
return "email_type";
|
|
97
|
+
return names[field] ?? field;
|
|
98
|
+
});
|
|
99
|
+
if (value.recipient_email && value.recipient_user_ids)
|
|
100
|
+
fields.push("recipient_email");
|
|
101
|
+
return { task, status: "needs_input", request_id: requestId, missing: [...new Set(fields)],
|
|
102
|
+
error: { code: "WECOM_INPUT_INVALID", message: "Choose exactly one recipient mode; content must fit 2048 UTF-8 bytes and safe mode is available only for text." } };
|
|
103
|
+
}
|
|
104
|
+
let client;
|
|
105
|
+
let recipientUserIds = value.recipient_user_ids;
|
|
106
|
+
// Shared runner preserves actionable authentication/configuration failures.
|
|
107
|
+
await dependencies.beforeExecute?.();
|
|
108
|
+
try {
|
|
109
|
+
client = dependencies.client ?? dependencies.clientFactory?.() ?? new WecomClient(loadConfig());
|
|
110
|
+
const caps = await client.capabilities();
|
|
111
|
+
if (!caps.enabled || !caps.configured)
|
|
112
|
+
return blocked("WECOM_CHANNEL_UNAVAILABLE", "The WeCom channel is disabled or not configured.", requestId);
|
|
113
|
+
if (!caps.messageTypes.includes(value.message_type))
|
|
114
|
+
return blocked("WECOM_MESSAGE_TYPE_UNSUPPORTED", "The channel does not support this message type.", requestId);
|
|
115
|
+
if ((recipientUserIds?.length ?? 1) > caps.maxRecipients)
|
|
116
|
+
return blocked("WECOM_RECIPIENT_LIMIT", "The requested recipients exceed the channel limit; reduce the explicit recipient list.", requestId);
|
|
117
|
+
const byteLimit = value.message_type === "text" ? caps.maxTextBytes : caps.maxMarkdownBytes;
|
|
118
|
+
if (Buffer.byteLength(value.content, "utf8") > byteLimit)
|
|
119
|
+
return blocked("WECOM_CONTENT_LIMIT", "The content exceeds the channel UTF-8 byte limit.", requestId);
|
|
120
|
+
if (value.recipient_email) {
|
|
121
|
+
const recipient = await client.recipientByEmail(value.recipient_email, value.email_type);
|
|
122
|
+
recipientUserIds = [recipient.userId];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
return safeError(error, requestId);
|
|
127
|
+
}
|
|
128
|
+
// Validate the resolved ID too: no mutation happens before the complete body is valid.
|
|
129
|
+
const resolved = SendMessageSchema.safeParse({ recipientUserIds, messageType: value.message_type, content: value.content, safe: value.safe });
|
|
130
|
+
if (!resolved.success)
|
|
131
|
+
return blocked("WECOM_RECIPIENT_INVALID", "The exact recipient could not be resolved to valid user IDs. Do not guess addresses or switch email types.", requestId);
|
|
132
|
+
try {
|
|
133
|
+
// Preserve mailbox + type in the POST: the server's idempotency fingerprint
|
|
134
|
+
// retains the original recipient resolution even if the mailbox later changes.
|
|
135
|
+
const receipt = await client.send(body.data, requestId);
|
|
136
|
+
if (receipt.requestId !== requestId || receipt.status === "UNKNOWN" || receipt.status === "SENDING")
|
|
137
|
+
return recover(client, requestId);
|
|
138
|
+
return receiptResult(receipt, requestId);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (error instanceof WecomError && error.code !== "WECOM_RESULT_UNKNOWN"
|
|
142
|
+
&& (error.code === "WECOM_INPUT_INVALID" || error.status !== undefined && error.status >= 400 && error.status < 500))
|
|
143
|
+
return safeError(error, requestId);
|
|
144
|
+
if (error instanceof Error && error.name === "AuthError")
|
|
145
|
+
return safeError(error, requestId);
|
|
146
|
+
// Once POST was attempted, transport and unexpected errors are conservatively uncertain.
|
|
147
|
+
return recover(client, requestId);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=wecom-notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wecom-notify.js","sourceRoot":"","sources":["../../src/tasks/wecom-notify.ts"],"names":[],"mappings":"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"}
|