@m1a0rz/agent-identity 0.2.5 → 0.3.2
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-cn.md +19 -9
- package/README.md +22 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -22
- package/dist/src/actions/identity-actions.d.ts +7 -1
- package/dist/src/actions/identity-actions.d.ts.map +1 -1
- package/dist/src/actions/identity-actions.js +82 -34
- package/dist/src/commands/identity-commands.d.ts.map +1 -1
- package/dist/src/commands/identity-commands.js +14 -5
- package/dist/src/hooks/after-tool-call.d.ts +12 -0
- package/dist/src/hooks/after-tool-call.d.ts.map +1 -0
- package/dist/src/hooks/after-tool-call.js +31 -0
- package/dist/src/hooks/before-agent-start.d.ts +3 -3
- package/dist/src/hooks/before-agent-start.d.ts.map +1 -1
- package/dist/src/hooks/before-agent-start.js +10 -22
- package/dist/src/hooks/before-tool-call.d.ts +20 -14
- package/dist/src/hooks/before-tool-call.d.ts.map +1 -1
- package/dist/src/hooks/before-tool-call.js +207 -127
- package/dist/src/hooks/llm-input.d.ts +2 -0
- package/dist/src/hooks/llm-input.d.ts.map +1 -1
- package/dist/src/hooks/llm-input.js +15 -4
- package/dist/src/hooks/sessions-send-propagation.d.ts +1 -0
- package/dist/src/hooks/sessions-send-propagation.d.ts.map +1 -1
- package/dist/src/hooks/sessions-send-propagation.js +4 -2
- package/dist/src/hooks/sessions-spawn-propagation.d.ts.map +1 -1
- package/dist/src/hooks/sessions-spawn-propagation.js +4 -2
- package/dist/src/hooks/subagent-ended-cleanup.d.ts +1 -0
- package/dist/src/hooks/subagent-ended-cleanup.d.ts.map +1 -1
- package/dist/src/hooks/subagent-ended-cleanup.js +4 -1
- package/dist/src/risk/low-risk-tools.d.ts.map +1 -1
- package/dist/src/risk/low-risk-tools.js +0 -2
- package/dist/src/services/tip-acquisition.d.ts +0 -1
- package/dist/src/services/tip-acquisition.d.ts.map +1 -1
- package/dist/src/services/tip-acquisition.js +2 -2
- package/dist/src/services/tip-propagation.d.ts.map +1 -1
- package/dist/src/services/tip-propagation.js +1 -2
- package/dist/src/services/tip-with-refresh.d.ts +1 -1
- package/dist/src/services/tip-with-refresh.d.ts.map +1 -1
- package/dist/src/services/tip-with-refresh.js +3 -5
- package/dist/src/store/credential-env-snapshot.d.ts +38 -0
- package/dist/src/store/credential-env-snapshot.d.ts.map +1 -0
- package/dist/src/store/credential-env-snapshot.js +101 -0
- package/dist/src/store/encryption.d.ts +30 -0
- package/dist/src/store/encryption.d.ts.map +1 -0
- package/dist/src/store/encryption.js +147 -0
- package/dist/src/store/group-sender-store.d.ts +35 -0
- package/dist/src/store/group-sender-store.d.ts.map +1 -0
- package/dist/src/store/group-sender-store.js +112 -0
- package/dist/src/store/session-store.d.ts.map +1 -1
- package/dist/src/store/session-store.js +91 -8
- package/dist/src/store/tip-store.d.ts +11 -6
- package/dist/src/store/tip-store.d.ts.map +1 -1
- package/dist/src/store/tip-store.js +23 -54
- package/dist/src/tools/identity-approve-tool.d.ts.map +1 -1
- package/dist/src/tools/identity-approve-tool.js +3 -1
- package/dist/src/tools/identity-fetch.d.ts.map +1 -1
- package/dist/src/tools/identity-fetch.js +3 -1
- package/dist/src/tools/identity-list-credentials.d.ts +2 -0
- package/dist/src/tools/identity-list-credentials.d.ts.map +1 -1
- package/dist/src/tools/identity-list-credentials.js +8 -4
- package/dist/src/tools/identity-login.d.ts.map +1 -1
- package/dist/src/tools/identity-login.js +2 -1
- package/dist/src/tools/identity-logout.d.ts.map +1 -1
- package/dist/src/tools/identity-logout.js +2 -1
- package/dist/src/tools/identity-set-binding.d.ts.map +1 -1
- package/dist/src/tools/identity-set-binding.js +2 -1
- package/dist/src/tools/identity-status.d.ts.map +1 -1
- package/dist/src/tools/identity-status.js +2 -1
- package/dist/src/tools/identity-unset-binding.d.ts.map +1 -1
- package/dist/src/tools/identity-unset-binding.js +2 -1
- package/dist/src/tools/identity-whoami.d.ts.map +1 -1
- package/dist/src/tools/identity-whoami.js +2 -1
- package/dist/src/utils/derive-session-key.d.ts +7 -0
- package/dist/src/utils/derive-session-key.d.ts.map +1 -1
- package/dist/src/utils/derive-session-key.js +84 -15
- package/package.json +1 -1
- package/skills/SKILL.md +75 -150
|
@@ -64,6 +64,18 @@ export function isSubagentSessionKey(sessionKey) {
|
|
|
64
64
|
return true;
|
|
65
65
|
return raw.includes(":subagent:");
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Check whether sessionKey represents a group/channel conversation.
|
|
69
|
+
* Examples:
|
|
70
|
+
* - agent:main:telegram:group:-1001
|
|
71
|
+
* - agent:main:slack:channel:C123456
|
|
72
|
+
*/
|
|
73
|
+
export function isGroupOrChannelSessionKey(sessionKey) {
|
|
74
|
+
const raw = (sessionKey ?? "").trim().toLowerCase();
|
|
75
|
+
if (!raw)
|
|
76
|
+
return false;
|
|
77
|
+
return raw.includes(":group:") || raw.includes(":channel:");
|
|
78
|
+
}
|
|
67
79
|
/**
|
|
68
80
|
* Resolve workload name for GetWorkloadAccessToken when roleTrn is not set.
|
|
69
81
|
* For subagent keys (agent:X:subagent:uuid or nested): use last segment (uuid) as workload name.
|
|
@@ -92,24 +104,81 @@ function normalizeAccountId(value) {
|
|
|
92
104
|
return trimmed || DEFAULT_ACCOUNT_ID;
|
|
93
105
|
}
|
|
94
106
|
/**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
* Extract group peer id from channel-specific "from/to" shapes.
|
|
108
|
+
* Return null for direct messages.
|
|
109
|
+
*/
|
|
98
110
|
function extractGroupPeerId(channel, from, to) {
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
111
|
+
const ch = (channel ?? "").trim().toLowerCase();
|
|
112
|
+
if (!ch)
|
|
101
113
|
return null;
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
return
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
const fromRaw = (from ?? "").trim();
|
|
115
|
+
const toRaw = (to ?? "").trim();
|
|
116
|
+
const pickByPrefix = (value, prefix) => {
|
|
117
|
+
if (!value)
|
|
118
|
+
return null;
|
|
119
|
+
if (!value.toLowerCase().startsWith(prefix.toLowerCase()))
|
|
120
|
+
return null;
|
|
121
|
+
const id = value.slice(prefix.length).trim();
|
|
122
|
+
return id || null;
|
|
123
|
+
};
|
|
124
|
+
const pickFirst = (...values) => {
|
|
125
|
+
for (const v of values) {
|
|
126
|
+
if (v)
|
|
127
|
+
return v;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
};
|
|
131
|
+
switch (ch) {
|
|
132
|
+
case "feishu":
|
|
133
|
+
// Group: to="chat:oc_xxx"; DM: to="user:ou_xxx"
|
|
134
|
+
return pickByPrefix(toRaw, "chat:");
|
|
135
|
+
case "telegram": {
|
|
136
|
+
// Group/topic: telegram:group:<chatId>[:topic:<threadId>]
|
|
137
|
+
const g1 = pickByPrefix(fromRaw, "telegram:group:");
|
|
138
|
+
if (g1)
|
|
139
|
+
return g1;
|
|
140
|
+
const g2 = pickByPrefix(toRaw, "telegram:group:");
|
|
141
|
+
if (g2)
|
|
142
|
+
return g2;
|
|
143
|
+
// Legacy fallback: telegram:-100... is usually group/supergroup
|
|
144
|
+
const f = pickByPrefix(fromRaw, "telegram:");
|
|
145
|
+
if (f && f.startsWith("-"))
|
|
146
|
+
return f;
|
|
147
|
+
const t = pickByPrefix(toRaw, "telegram:");
|
|
148
|
+
if (t && t.startsWith("-"))
|
|
149
|
+
return t;
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
case "slack":
|
|
153
|
+
// Group/channel: slack:channel:<id> / slack:group:<id>, to=channel:<id>
|
|
154
|
+
return pickFirst(pickByPrefix(fromRaw, "slack:channel:"), pickByPrefix(fromRaw, "slack:group:"), pickByPrefix(toRaw, "channel:"));
|
|
155
|
+
case "discord":
|
|
156
|
+
// Guild/thread channel: discord:channel:<id>, to=channel:<id>; DM uses user:<id>
|
|
157
|
+
return pickFirst(pickByPrefix(fromRaw, "discord:channel:"), pickByPrefix(toRaw, "channel:"));
|
|
158
|
+
case "signal":
|
|
159
|
+
// Group: group:<id>; DM: signal:<recipient>
|
|
160
|
+
return pickFirst(pickByPrefix(fromRaw, "group:"), pickByPrefix(toRaw, "group:"));
|
|
161
|
+
case "imessage":
|
|
162
|
+
// Group: imessage:group:<id>, to=chat_id:<id>; DM: imessage:<sender>
|
|
163
|
+
return pickFirst(pickByPrefix(fromRaw, "imessage:group:"), pickByPrefix(toRaw, "chat_id:"));
|
|
164
|
+
case "whatsapp":
|
|
165
|
+
// Group JID ends with @g.us; DM is E.164-like
|
|
166
|
+
if (/@g\.us$/i.test(fromRaw))
|
|
167
|
+
return fromRaw;
|
|
168
|
+
return null;
|
|
169
|
+
case "line":
|
|
170
|
+
// Group/room: line:group:<id> / line:room:<id>
|
|
171
|
+
return pickFirst(pickByPrefix(fromRaw, "line:group:"), pickByPrefix(fromRaw, "line:room:"), pickByPrefix(toRaw, "line:group:"), pickByPrefix(toRaw, "line:room:"));
|
|
172
|
+
case "matrix":
|
|
173
|
+
// Group/channel: matrix:channel:<roomId>; DM: matrix:<userId>
|
|
174
|
+
return pickByPrefix(fromRaw, "matrix:channel:");
|
|
175
|
+
case "msteams":
|
|
176
|
+
// Group/channel: msteams:channel:<id> / msteams:group:<id>, to=conversation:<id>
|
|
177
|
+
return pickFirst(pickByPrefix(fromRaw, "msteams:channel:"), pickByPrefix(fromRaw, "msteams:group:"), pickByPrefix(toRaw, "conversation:"));
|
|
178
|
+
default:
|
|
179
|
+
// Safe generic fallback: only explicit group/channel markers.
|
|
180
|
+
return pickFirst(pickByPrefix(fromRaw, `${ch}:group:`), pickByPrefix(fromRaw, `${ch}:channel:`), pickByPrefix(toRaw, `${ch}:group:`), pickByPrefix(toRaw, `${ch}:channel:`));
|
|
111
181
|
}
|
|
112
|
-
return null;
|
|
113
182
|
}
|
|
114
183
|
/**
|
|
115
184
|
* Derive sessionKey from command context.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m1a0rz/agent-identity",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Agent Identity: UserPool (用户池) login, TIP token (工作负载令牌), credential hosting (凭据托管 OAuth2/API key), optional tool/skill permission control (CheckPermission) and risk approval. Integrates with Volcengine 智能体身份和权限管理平台.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/skills/SKILL.md
CHANGED
|
@@ -16,59 +16,21 @@ metadata:
|
|
|
16
16
|
|
|
17
17
|
# Agent Identity
|
|
18
18
|
|
|
19
|
-
Use the agent-identity plugin for UserPool OIDC login
|
|
20
|
-
|
|
21
|
-
**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| `/identity list-credentials` or `/identity list [page]` | List providers and credentials |
|
|
35
|
-
| `/identity list-tips` | List valid TIP tokens |
|
|
36
|
-
| `/identity config` | Show plugin config (redacted) |
|
|
37
|
-
| `/identity fetch <provider> [--flow=...]` | Add credential |
|
|
38
|
-
| `/identity set <provider> <envVar>` | Bind credential to env var |
|
|
39
|
-
| `/identity unset <provider>` | Remove env binding |
|
|
40
|
-
| `/identity risk <command>` | Diagnose risk for a shell command |
|
|
41
|
-
| `/identity risk-patterns` | List built-in risky patterns |
|
|
42
|
-
| `/identity approve <approval_id>` | Approve high-risk tool call (user runs this; agent must not self-approve) |
|
|
43
|
-
| `/identity reject <approval_id>` | Reject high-risk tool call |
|
|
44
|
-
|
|
45
|
-
## Tools Overview
|
|
46
|
-
|
|
47
|
-
| Tool | Params | Purpose |
|
|
48
|
-
| --------------------------- | ---------------------------------------------- | ------------------------------------------ |
|
|
49
|
-
| `identity_whoami` | — | Identity brief: sub, login time, TIP expiry |
|
|
50
|
-
| `identity_status` | — | Full status: session/TIP (issued, expires, chain), credentials, bindings |
|
|
51
|
-
| `identity_login` | — | Start OIDC login or refresh TIP |
|
|
52
|
-
| `identity_logout` | — | Clear session and TIP |
|
|
53
|
-
| `identity_list_credentials` | `page?` | List providers and credentials (paginated) |
|
|
54
|
-
| `identity_list_tips` | — | List valid TIP tokens and bindings |
|
|
55
|
-
| `identity_config` | — | Show plugin config (secrets redacted) |
|
|
56
|
-
| `identity_config_suggest` | `intent?`, `lang?` | Generate config snippets for openclaw.json |
|
|
57
|
-
| `identity_fetch` | `provider`, `flow?`, `redirectUrl?`, `scopes?` | Add credential |
|
|
58
|
-
| `identity_set_binding` | `provider`, `envVar` | Bind provider → env var for tool injection |
|
|
59
|
-
| `identity_unset_binding` | `provider` | Remove env binding |
|
|
60
|
-
| `identity_approve_tool` | `approval_id` | Approve a high-risk tool call |
|
|
61
|
-
| `identity_risk_check` | `command?`, `toolName?`, `params?` | Diagnose risk for command or tool call |
|
|
62
|
-
| `identity_list_risk_patterns` | — | List built-in risky patterns and paths |
|
|
63
|
-
|
|
64
|
-
## Risk Detection and Approval
|
|
65
|
-
|
|
66
|
-
When `authz.requireRiskApproval` is on, the plugin classifies tool calls (e.g. exec, write, apply_patch) by risk. User-provided commands and file paths are evaluated:
|
|
67
|
-
|
|
68
|
-
- **Rule-based**: Destructive patterns (rm -rf, sudo, curl|bash), sensitive paths (/etc, ~/.ssh).
|
|
69
|
-
- **LLM-based** (optional): When rules return "medium", an LLM re-evaluates for context (`authz.enableLlmRiskCheck`).
|
|
70
|
-
|
|
71
|
-
High-risk calls require user approval. The approval message and block reason include the LLM risk explanation when available (e.g. "Pipe-to-shell: network fetch piped to shell execution").
|
|
19
|
+
Use the agent-identity plugin for UserPool OIDC login, TIP token, credential hosting (OAuth2, API key), and optional tool risk approval (AuthZ).
|
|
20
|
+
|
|
21
|
+
**Agent rules:**
|
|
22
|
+
|
|
23
|
+
- Call tools directly. Never suggest slash commands to the user.
|
|
24
|
+
- When any tool returns an `authUrl` field, **always display it as a markdown link** to the user, e.g. `[Click here to log in](https://...)` or `[Click here to authorize](https://...)`. Never paste the bare URL as plain text — long OAuth URLs with special characters get truncated by chat platforms.
|
|
25
|
+
- Never call `identity_approve_tool` to self-approve. High-risk approval is a human action only.
|
|
26
|
+
- **Critical — auto-login on AuthZ block:** When ANY tool call fails with an error containing "TIP token required" or "session has no valid identity", you MUST immediately call `identity_login` to initiate login, display the `authUrl` to the user, and wait for them to complete authentication. After login succeeds, retry the original tool call. Do NOT skip the blocked action, try alternative approaches, or tell the user to run commands manually.
|
|
27
|
+
- **Critical — always report permission errors to the user:** When a tool call is blocked with errors like "CheckPermission denied", "permission denied", "requires approval", or any `[agent-identity]` prefixed error, you MUST:
|
|
28
|
+
1. **Tell the user clearly** what was blocked and why (include the tool/skill name and the error message).
|
|
29
|
+
2. **Never silently ignore** the error or skip to something else without informing the user.
|
|
30
|
+
3. For "CheckPermission denied for skill ..." — tell the user they do not have access to that skill and suggest contacting an administrator.
|
|
31
|
+
4. For "CheckPermission denied for tool ..." — tell the user the tool is restricted and they lack permission to use it.
|
|
32
|
+
5. For "High-risk tool requires approval" — relay the approval instructions (approval ID, timeout) and wait for the user to approve before retrying.
|
|
33
|
+
6. For "Failed to verify permission" — report a temporary error and suggest retrying later.
|
|
72
34
|
|
|
73
35
|
## Tool Parameters
|
|
74
36
|
|
|
@@ -76,44 +38,49 @@ High-risk calls require user approval. The approval message and block reason inc
|
|
|
76
38
|
|
|
77
39
|
Starts OIDC login or refreshes TIP. **Call when:** "login", "登录", "sign in", "我需要先登录". Required before `identity_fetch`. No params.
|
|
78
40
|
|
|
41
|
+
**Returns:**
|
|
42
|
+
|
|
43
|
+
- Already logged in: `{ ok: true, sub, message }` — inform user they are already authenticated.
|
|
44
|
+
- Needs login: `{ ok: false, authUrl, message }` — **you MUST display the `authUrl` as a markdown link** and tell them to open it in a browser. After they authorize, a success message will be sent to the chat automatically. Example response: "Please complete login in your browser: [Click here to log in](authUrl)"
|
|
45
|
+
- Error: `{ error, authUrl: null }` — report the error.
|
|
46
|
+
|
|
79
47
|
### identity_whoami
|
|
80
48
|
|
|
81
|
-
Brief identity check. **Call when:** "who am I", "查身份", "am I logged in", "当前登录状态"
|
|
49
|
+
Brief identity check. **Call when:** "who am I", "查身份", "am I logged in", "当前登录状态". No params.
|
|
82
50
|
|
|
83
|
-
Returns: `sub`, `hasTip`, `loggedIn`, `sessionLoginAt`, `sessionExpiresAt`, `tipIssuedAt`, `tipExpiresAt`, `tipExpiresInSeconds`, `tipChain`.
|
|
51
|
+
Returns: `sub`, `hasTip`, `loggedIn`, `sessionLoginAt`, `sessionExpiresAt`, `tipIssuedAt`, `tipExpiresAt`, `tipExpiresInSeconds`, `tipChain`.
|
|
84
52
|
|
|
85
53
|
### identity_status
|
|
86
54
|
|
|
87
|
-
Full status including credentials and bindings. **Call when:** "status", "查看完整状态", "我的凭据和绑定", "show my credentials and bindings"
|
|
55
|
+
Full status including credentials and bindings. **Call when:** "status", "查看完整状态", "我的凭据和绑定", "show my credentials and bindings". No params.
|
|
88
56
|
|
|
89
|
-
Returns: `loggedIn`, `sub`, `hasTip`, `session` (loginAt, expiresAt), `tip` (issuedAt, expiresAt, chain), `credentialProviders`, `bindings`.
|
|
57
|
+
Returns: `loggedIn`, `sub`, `hasTip`, `session` (loginAt, expiresAt), `tip` (issuedAt, expiresAt, chain), `credentialProviders`, `bindings`.
|
|
90
58
|
|
|
91
|
-
###
|
|
59
|
+
### identity_logout
|
|
92
60
|
|
|
93
|
-
|
|
61
|
+
Clear session and TIP. **Call when:** "logout", "登出", "sign out". No params.
|
|
94
62
|
|
|
95
|
-
|
|
63
|
+
### identity_list_credentials
|
|
96
64
|
|
|
97
|
-
|
|
98
|
-
| ------ | ------ | -------- | ------------------------ |
|
|
99
|
-
| `page` | number | No | Page number (default: 1) |
|
|
65
|
+
Lists available credential providers and stored credentials. Supports filtering by name or flow to locate a specific provider without paging through all results. **Call when:** "有哪些服务可以连接", "what providers are available", "我添加了哪些凭据", "list my credentials", "查找某个 provider"
|
|
100
66
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
67
|
+
| Param | Type | Required | Description |
|
|
68
|
+
| ------ | ------ | -------- | ------------------------------------------------------------------ |
|
|
69
|
+
| `page` | number | No | Page number (default: 1) |
|
|
70
|
+
| `name` | string | No | Filter providers by name (exact or prefix match) |
|
|
71
|
+
| `flow` | string | No | Filter providers by flow, e.g. `M2M` or `USER_FEDERATION` |
|
|
72
|
+
|
|
73
|
+
When looking for a specific provider (e.g. before `identity_fetch`), prefer passing `name` filter instead of paging through results.
|
|
104
74
|
|
|
105
75
|
Returns: `providers`, `storedOnly`, `page`, `hasMore`.
|
|
106
76
|
|
|
107
77
|
### identity_fetch
|
|
108
78
|
|
|
109
|
-
Adds a credential for a provider (OAuth2 or API key). **Call
|
|
110
|
-
|
|
111
|
-
**User prompts that mean "call identity_fetch":**
|
|
79
|
+
Adds a credential for a provider (OAuth2 or API key). **Call when the user wants to add, get, or configure credentials:**
|
|
112
80
|
|
|
113
|
-
-
|
|
114
|
-
- 中文: "帮我添加/获取 Google 凭据", "配置 OpenAI 的 API key", "连接我的 GitHub", "我要用某某服务但没有密钥", "授权访问某平台", "添加某某的 token", "获取某某的凭证"
|
|
81
|
+
- "帮我添加 Google 凭据", "get credentials for OpenAI", "connect my GitHub", "配置 API key", "授权访问某平台"
|
|
115
82
|
|
|
116
|
-
First ensure user is logged in (`identity_whoami`); if not, use `identity_login`. Then call `identity_fetch` with the provider.
|
|
83
|
+
First ensure user is logged in (`identity_whoami`); if not, use `identity_login`. Then call `identity_fetch` with the provider.
|
|
117
84
|
|
|
118
85
|
| Param | Type | Required | Description |
|
|
119
86
|
| ------------- | -------- | -------- | --------------------------------------------------------------------------------------- |
|
|
@@ -121,39 +88,26 @@ First ensure user is logged in (`identity_whoami`); if not, use `identity_login`
|
|
|
121
88
|
| `flow` | string | No | `oauth2-user` (default for 3LO), `oauth2-m2m`, or `apikey`. Auto-inferred when omitted. |
|
|
122
89
|
| `redirectUrl` | string | No | OAuth redirect URL (when provider requires custom) |
|
|
123
90
|
| `scopes` | string[] | No | OAuth scopes (e.g. `["email", "profile"]`) |
|
|
124
|
-
| `returnValue` | boolean | No | When true and fetch succeeds, include credential `value` in result
|
|
125
|
-
|
|
126
|
-
```json
|
|
127
|
-
{ "provider": "google" }
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
```json
|
|
131
|
-
{ "provider": "openai", "flow": "apikey", "returnValue": true }
|
|
132
|
-
```
|
|
91
|
+
| `returnValue` | boolean | No | When true and fetch succeeds, include credential `value` in result. Default false. |
|
|
133
92
|
|
|
134
93
|
**Response:**
|
|
135
94
|
|
|
136
|
-
- **OAuth2-user**:
|
|
137
|
-
- **OAuth2-
|
|
95
|
+
- **OAuth2-user (success: true)**: Server had a cached token — credential added immediately. No further action needed.
|
|
96
|
+
- **OAuth2-user (authUrl)**: User must authorize. **Display as markdown link** `[Click here to authorize](authUrl)`. A background process will detect when authorization completes and trigger the agent to continue automatically. If that does not happen within a reasonable time, **call `identity_fetch` again with the same provider** to check status.
|
|
97
|
+
- **OAuth2-m2m** / **apikey**: `success: true`, `message` (completes immediately). If `returnValue: true`, also includes `value`.
|
|
138
98
|
|
|
139
99
|
### identity_set_binding
|
|
140
100
|
|
|
141
|
-
Binds a stored credential to an env var
|
|
142
|
-
|
|
143
|
-
**User prompts:** "让工具能用我的 Google 凭据", "bind/google my credential for tools", "把 Google token 注入给 agent", "inject my OpenAI key for API calls", "配置某某凭据给工具用"
|
|
101
|
+
Binds a stored credential to an env var for tool injection. **Call when:** "让工具能用我的凭据", "bind my credential for tools", "inject my key for API calls"
|
|
144
102
|
|
|
145
|
-
Credential must exist first (`identity_fetch`). Common env vars: `GOOGLE_ACCESS_TOKEN`, `OPENAI_API_KEY`, `GITHUB_TOKEN
|
|
103
|
+
Credential must exist first (`identity_fetch`). Common env vars: `GOOGLE_ACCESS_TOKEN`, `OPENAI_API_KEY`, `GITHUB_TOKEN`.
|
|
146
104
|
|
|
147
105
|
| Param | Type | Required | Description |
|
|
148
106
|
| ---------- | ------ | -------- | ---------------------------------------------------------------------------------------- |
|
|
149
107
|
| `provider` | string | Yes | Provider name (e.g. `google`) |
|
|
150
108
|
| `envVar` | string | Yes | Env var for injection (e.g. `GOOGLE_ACCESS_TOKEN`). Must match `[A-Za-z_][A-Za-z0-9_]*`. |
|
|
151
109
|
|
|
152
|
-
|
|
153
|
-
{ "provider": "google", "envVar": "GOOGLE_ACCESS_TOKEN" }
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
If credential exists: binds it. Else: imports from `process.env[envVar]` as api_key (gateway must have that env set).
|
|
110
|
+
If credential exists: binds it. Else: imports from `process.env[envVar]` as api_key.
|
|
157
111
|
|
|
158
112
|
### identity_unset_binding
|
|
159
113
|
|
|
@@ -161,86 +115,57 @@ If credential exists: binds it. Else: imports from `process.env[envVar]` as api_
|
|
|
161
115
|
| ---------- | ------ | -------- | --------------------------------------- |
|
|
162
116
|
| `provider` | string | Yes | Provider name to unbind (e.g. `google`) |
|
|
163
117
|
|
|
164
|
-
```json
|
|
165
|
-
{ "provider": "google" }
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### identity_approve_tool
|
|
169
|
-
|
|
170
|
-
| Param | Type | Required | Description |
|
|
171
|
-
| ------------- | ------ | -------- | --------------------------------------------------------------------------- |
|
|
172
|
-
| `approval_id` | string | Yes | ID from the approval prompt (e.g. after blocking a high-risk exec/write) |
|
|
173
|
-
|
|
174
|
-
Optional tool (not given to agent by default). For human approval, use `/identity approve <id>` or reply "approve" in chat. The agent must NOT call this tool to self-approve. The approval prompt includes the LLM risk reason when available.
|
|
175
|
-
|
|
176
|
-
```json
|
|
177
|
-
{ "approval_id": "abc123" }
|
|
178
|
-
```
|
|
179
|
-
|
|
180
118
|
### identity_risk_check
|
|
181
119
|
|
|
182
|
-
Evaluates risk of a command or tool call
|
|
120
|
+
Evaluates risk of a command or tool call. **Call when:** "这个命令安全吗", "is this risky", "帮我评估风险"
|
|
183
121
|
|
|
184
|
-
| Param | Type | Required | Description
|
|
185
|
-
| ---------- | -------- | -------- |
|
|
186
|
-
| `command` | string | No* | Shell command to evaluate
|
|
187
|
-
| `toolName` | string | No* | Tool name (e.g. write, apply_patch). Use with params
|
|
188
|
-
| `params` | object | No | Tool params
|
|
122
|
+
| Param | Type | Required | Description |
|
|
123
|
+
| ---------- | -------- | -------- | ------------------------------------------------------ |
|
|
124
|
+
| `command` | string | No* | Shell command to evaluate |
|
|
125
|
+
| `toolName` | string | No* | Tool name (e.g. write, apply_patch). Use with `params`. |
|
|
126
|
+
| `params` | object | No | Tool params |
|
|
189
127
|
|
|
190
|
-
*Provide either `command` or `toolName`. Returns `risk`, `reason`, `source
|
|
191
|
-
|
|
192
|
-
```json
|
|
193
|
-
{ "command": "rm -rf /" }
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
```json
|
|
197
|
-
{ "toolName": "write", "params": { "path": "/etc/hosts", "content": "..." } }
|
|
198
|
-
```
|
|
128
|
+
*Provide either `command` or `toolName`. Returns `risk`, `reason`, `source`.
|
|
199
129
|
|
|
200
130
|
### identity_list_risk_patterns
|
|
201
131
|
|
|
202
|
-
Returns built-in dangerous command patterns and sensitive paths. No params.
|
|
203
|
-
|
|
204
|
-
```json
|
|
205
|
-
{}
|
|
206
|
-
```
|
|
132
|
+
Returns built-in dangerous command patterns and sensitive paths. No params.
|
|
207
133
|
|
|
208
134
|
### identity_config_suggest
|
|
209
135
|
|
|
210
|
-
Generates config snippets
|
|
136
|
+
Generates config snippets. **Call when:** "如何配置 identity 插件", "帮我配置登录", "怎么开启权限检查"
|
|
211
137
|
|
|
212
138
|
| Param | Type | Required | Description |
|
|
213
139
|
| ------- | ------ | -------- | --------------------------------------------------------------------------- |
|
|
214
|
-
| `intent`| string | No | `identity
|
|
215
|
-
| `lang` | string | No | `en` or `zh
|
|
140
|
+
| `intent`| string | No | `identity`, `userpool`, `authz`, `llm_risk`, or `full` (default) |
|
|
141
|
+
| `lang` | string | No | `en` or `zh`. Default: en |
|
|
216
142
|
|
|
217
|
-
Returns: `configPath`, `config` (JSON to merge), `instructions`, `nextSteps`.
|
|
143
|
+
Returns: `configPath`, `config` (JSON to merge), `instructions`, `nextSteps`.
|
|
218
144
|
|
|
219
|
-
|
|
220
|
-
{ "intent": "userpool", "lang": "zh" }
|
|
221
|
-
```
|
|
145
|
+
### identity_list_tips
|
|
222
146
|
|
|
223
|
-
|
|
147
|
+
List valid TIP tokens and bindings. No params.
|
|
224
148
|
|
|
225
|
-
|
|
226
|
-
2. **Add credential**: `identity_fetch` with `provider`. For OAuth2-user, tell user to open `authUrl`; success message sent when done.
|
|
227
|
-
3. **Bind for tools** (optional): `identity_set_binding` so the credential is injected as an env var when tools run.
|
|
149
|
+
### identity_approve_tool
|
|
228
150
|
|
|
229
|
-
|
|
151
|
+
| Param | Type | Required | Description |
|
|
152
|
+
| ------------- | ------ | -------- | -------------------------------------------------------- |
|
|
153
|
+
| `approval_id` | string | Yes | ID from the approval prompt |
|
|
230
154
|
|
|
231
|
-
|
|
232
|
-
2. **List patterns**: `identity_list_risk_patterns` to see what triggers high-risk approval.
|
|
155
|
+
**Agent must NOT call this tool.** This is for human approval only — user runs `/identity approve <id>` or replies "approve" in chat.
|
|
233
156
|
|
|
234
|
-
##
|
|
157
|
+
## Workflow: Adding a Credential
|
|
158
|
+
|
|
159
|
+
1. **Check login**: `identity_whoami`. If not logged in, call `identity_login`. When it returns `authUrl`, **display as markdown link** `[Click here to log in](authUrl)`.
|
|
160
|
+
2. **Add credential**: `identity_fetch` with `provider`. If it returns `authUrl`, display the link. The agent will be notified automatically when the user completes authorization. If not resumed automatically, **call `identity_fetch` again** to check status.
|
|
161
|
+
3. **Bind for tools** (optional): `identity_set_binding` so the credential is injected as an env var when tools run.
|
|
235
162
|
|
|
236
|
-
|
|
163
|
+
## Workflow: Checking Risk
|
|
237
164
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
- `authz`: Optional AuthZ (toolCheck, skillReadCheck, requireRiskApproval, enableLlmRiskCheck, llmRiskCheck, namespaceName, lowRiskBypass). When `enableLlmRiskCheck` is true, rules returning "medium" are re-evaluated via LLM; the risk reason is shown in approval prompts and block messages.
|
|
165
|
+
1. `identity_risk_check` with `command` or `toolName`+`params`. Returns risk level and reason.
|
|
166
|
+
2. `identity_list_risk_patterns` to see what triggers high-risk.
|
|
241
167
|
|
|
242
168
|
## Notes
|
|
243
169
|
|
|
244
|
-
-
|
|
245
|
-
-
|
|
246
|
-
- `identity_risk_check` and `identity_list_risk_patterns` do not require login.
|
|
170
|
+
- `identity_login`, `identity_logout`, `identity_whoami`, `identity_status`, and `identity_config_suggest` work without login.
|
|
171
|
+
- `identity_risk_check` and `identity_list_risk_patterns` work without login.
|