feat(agent): DingTalk channel binding support in instance controller + system prompt
- agent-instance.controller.ts: accept dingTalkClientId/dingTalkClientSecret in POST /instances body, forward to deploy service - system-prompt-builder.ts: add DingTalk 5-step binding guide for iAgent so the AI can walk users through connecting their DingTalk account Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b0801e0983
commit
5ec6f113cd
|
|
@ -44,7 +44,16 @@ export class SystemPromptBuilder {
|
||||||
'When a user asks to create a OpenClaw / 小龙虾 / personal AI agent / autonomous agent:\n' +
|
'When a user asks to create a OpenClaw / 小龙虾 / personal AI agent / autonomous agent:\n' +
|
||||||
'1. Ask for a name if not given\n' +
|
'1. Ask for a name if not given\n' +
|
||||||
'2. Use the Current User ID from this prompt as userId\n' +
|
'2. Use the Current User ID from this prompt as userId\n' +
|
||||||
'3. Call the create API with Bash and report the result (id, status, containerName)',
|
'3. Call the create API with Bash and report the result (id, status, containerName)\n\n' +
|
||||||
|
'## DingTalk Channel Binding (钉钉接入)\n' +
|
||||||
|
'To bind a DingTalk bot to an OpenClaw instance, the user needs a DingTalk app with Stream mode enabled:\n' +
|
||||||
|
' Step 1: Go to https://open.dingtalk.com/developer → "创建应用" → Enterprise Internal App\n' +
|
||||||
|
' Step 2: Enable "机器人" → set message receive mode to "Stream模式"\n' +
|
||||||
|
' Step 3: Copy the AppKey (ClientId) and AppSecret (ClientSecret)\n' +
|
||||||
|
' Step 4: Create/re-deploy the OpenClaw instance with DingTalk creds:\n' +
|
||||||
|
' wget -q -O- --post-data=\'{"name":"<name>","userId":"<userId>","usePool":true,"dingTalkClientId":"<appKey>","dingTalkClientSecret":"<appSecret>"}\' \\\n' +
|
||||||
|
' --header="Content-Type: application/json" http://localhost:3002/api/v1/agent/instances\n' +
|
||||||
|
' Step 5: Tell the user to add the bot to a DingTalk group or send it a direct message — it will respond via OpenClaw AI.',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tenant + user context
|
// Tenant + user context
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ export class AgentInstanceController {
|
||||||
sshPort?: number;
|
sshPort?: number;
|
||||||
sshUser?: string;
|
sshUser?: string;
|
||||||
sshKey?: string; // plaintext private key, only used if usePool=false
|
sshKey?: string; // plaintext private key, only used if usePool=false
|
||||||
|
// Optional: DingTalk channel binding
|
||||||
|
dingTalkClientId?: string;
|
||||||
|
dingTalkClientSecret?: string;
|
||||||
}) {
|
}) {
|
||||||
if (!body.name || !body.userId) {
|
if (!body.name || !body.userId) {
|
||||||
throw new BadRequestException('name and userId are required');
|
throw new BadRequestException('name and userId are required');
|
||||||
|
|
@ -66,9 +69,12 @@ export class AgentInstanceController {
|
||||||
instance.config = {};
|
instance.config = {};
|
||||||
instance.hostPort = 0; // Will be set by deploy service
|
instance.hostPort = 0; // Will be set by deploy service
|
||||||
|
|
||||||
|
const dtClientId = body.dingTalkClientId;
|
||||||
|
const dtClientSecret = body.dingTalkClientSecret;
|
||||||
|
|
||||||
if (body.usePool !== false) {
|
if (body.usePool !== false) {
|
||||||
await this.instanceRepo.save(instance);
|
await this.instanceRepo.save(instance);
|
||||||
this.deployService.deployFromPool(instance, this.claudeApiKey)
|
this.deployService.deployFromPool(instance, this.claudeApiKey, dtClientId, dtClientSecret)
|
||||||
.then(() => this.instanceRepo.save(instance))
|
.then(() => this.instanceRepo.save(instance))
|
||||||
.catch(async (err) => {
|
.catch(async (err) => {
|
||||||
instance.status = 'error';
|
instance.status = 'error';
|
||||||
|
|
@ -83,7 +89,7 @@ export class AgentInstanceController {
|
||||||
instance.sshPort = body.sshPort ?? 22;
|
instance.sshPort = body.sshPort ?? 22;
|
||||||
instance.sshUser = body.sshUser;
|
instance.sshUser = body.sshUser;
|
||||||
await this.instanceRepo.save(instance);
|
await this.instanceRepo.save(instance);
|
||||||
this.deployService.deployToUserServer(instance, body.sshKey, this.claudeApiKey)
|
this.deployService.deployToUserServer(instance, body.sshKey, this.claudeApiKey, dtClientId, dtClientSecret)
|
||||||
.then(() => this.instanceRepo.save(instance))
|
.then(() => this.instanceRepo.save(instance))
|
||||||
.catch(async (err) => {
|
.catch(async (err) => {
|
||||||
instance.status = 'error';
|
instance.status = 'error';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue