@m1a0rz/agent-identity 0.4.1 → 0.4.3

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.
Files changed (131) hide show
  1. package/README-cn.md +32 -19
  2. package/README.md +32 -19
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +80 -7
  5. package/dist/scripts/demo-get-session.d.ts +15 -0
  6. package/dist/scripts/demo-get-session.d.ts.map +1 -0
  7. package/dist/scripts/demo-get-session.js +58 -0
  8. package/dist/src/actions/identity-actions.d.ts +74 -8
  9. package/dist/src/actions/identity-actions.d.ts.map +1 -1
  10. package/dist/src/actions/identity-actions.js +217 -84
  11. package/dist/src/commands/identity-commands.d.ts.map +1 -1
  12. package/dist/src/commands/identity-commands.js +139 -11
  13. package/dist/src/gateway/identity-session-methods.d.ts +2 -2
  14. package/dist/src/gateway/identity-session-methods.d.ts.map +1 -1
  15. package/dist/src/gateway/identity-session-methods.js +9 -5
  16. package/dist/src/hooks/after-tool-call.d.ts.map +1 -1
  17. package/dist/src/hooks/after-tool-call.js +12 -0
  18. package/dist/src/hooks/before-agent-start.d.ts +2 -0
  19. package/dist/src/hooks/before-agent-start.d.ts.map +1 -1
  20. package/dist/src/hooks/before-agent-start.js +33 -6
  21. package/dist/src/hooks/before-tool-call.d.ts +1 -0
  22. package/dist/src/hooks/before-tool-call.d.ts.map +1 -1
  23. package/dist/src/hooks/before-tool-call.js +29 -5
  24. package/dist/src/hooks/llm-input.d.ts.map +1 -1
  25. package/dist/src/hooks/llm-input.js +32 -4
  26. package/dist/src/hooks/sessions-send-propagation.d.ts.map +1 -1
  27. package/dist/src/hooks/sessions-send-propagation.js +1 -0
  28. package/dist/src/hooks/sessions-spawn-propagation.d.ts.map +1 -1
  29. package/dist/src/hooks/sessions-spawn-propagation.js +1 -0
  30. package/dist/src/hooks/tool-result-persist.d.ts +20 -0
  31. package/dist/src/hooks/tool-result-persist.d.ts.map +1 -0
  32. package/dist/src/hooks/tool-result-persist.js +50 -0
  33. package/dist/src/preflight/plugin-preflight.d.ts +55 -0
  34. package/dist/src/preflight/plugin-preflight.d.ts.map +1 -0
  35. package/dist/src/preflight/plugin-preflight.js +226 -0
  36. package/dist/src/preflight/plugin-state.d.ts +18 -0
  37. package/dist/src/preflight/plugin-state.d.ts.map +1 -0
  38. package/dist/src/preflight/plugin-state.js +19 -0
  39. package/dist/src/routes/oidc-login.js +2 -2
  40. package/dist/src/services/identity-client.d.ts +129 -2
  41. package/dist/src/services/identity-client.d.ts.map +1 -1
  42. package/dist/src/services/identity-client.js +175 -20
  43. package/dist/src/services/identity-credentials.d.ts +1 -1
  44. package/dist/src/services/identity-credentials.d.ts.map +1 -1
  45. package/dist/src/services/identity-credentials.js +32 -16
  46. package/dist/src/services/oidc-client.d.ts +12 -1
  47. package/dist/src/services/oidc-client.d.ts.map +1 -1
  48. package/dist/src/services/oidc-client.js +20 -3
  49. package/dist/src/services/session-refresh.d.ts +10 -0
  50. package/dist/src/services/session-refresh.d.ts.map +1 -1
  51. package/dist/src/services/session-refresh.js +29 -5
  52. package/dist/src/services/skill-contract-metadata.d.ts +35 -0
  53. package/dist/src/services/skill-contract-metadata.d.ts.map +1 -0
  54. package/dist/src/services/skill-contract-metadata.js +145 -0
  55. package/dist/src/services/skill-contract-renderer.d.ts +14 -0
  56. package/dist/src/services/skill-contract-renderer.d.ts.map +1 -0
  57. package/dist/src/services/skill-contract-renderer.js +120 -0
  58. package/dist/src/services/tip-propagation.d.ts +2 -0
  59. package/dist/src/services/tip-propagation.d.ts.map +1 -1
  60. package/dist/src/services/tip-propagation.js +4 -3
  61. package/dist/src/services/tip-with-refresh.d.ts +1 -1
  62. package/dist/src/services/tip-with-refresh.d.ts.map +1 -1
  63. package/dist/src/services/tip-with-refresh.js +24 -39
  64. package/dist/src/store/credential-store.d.ts +6 -1
  65. package/dist/src/store/credential-store.d.ts.map +1 -1
  66. package/dist/src/store/credential-store.js +3 -0
  67. package/dist/src/store/oidc-state-store.d.ts +3 -3
  68. package/dist/src/store/oidc-state-store.d.ts.map +1 -1
  69. package/dist/src/store/oidc-state-store.js +2 -2
  70. package/dist/src/store/sender-session-store.d.ts +8 -0
  71. package/dist/src/store/sender-session-store.d.ts.map +1 -1
  72. package/dist/src/store/sender-session-store.js +34 -1
  73. package/dist/src/store/skill-contract-store.d.ts +19 -0
  74. package/dist/src/store/skill-contract-store.d.ts.map +1 -0
  75. package/dist/src/store/skill-contract-store.js +65 -0
  76. package/dist/src/store/skill-path-store.d.ts +5 -0
  77. package/dist/src/store/skill-path-store.d.ts.map +1 -1
  78. package/dist/src/store/skill-path-store.js +13 -1
  79. package/dist/src/tools/identity-approve-tool.d.ts +2 -11
  80. package/dist/src/tools/identity-approve-tool.d.ts.map +1 -1
  81. package/dist/src/tools/identity-config-suggest.d.ts +2 -13
  82. package/dist/src/tools/identity-config-suggest.d.ts.map +1 -1
  83. package/dist/src/tools/identity-config.d.ts +2 -7
  84. package/dist/src/tools/identity-config.d.ts.map +1 -1
  85. package/dist/src/tools/identity-fetch.d.ts +2 -13
  86. package/dist/src/tools/identity-fetch.d.ts.map +1 -1
  87. package/dist/src/tools/identity-fetch.js +3 -3
  88. package/dist/src/tools/identity-get-role-credentials.d.ts +10 -0
  89. package/dist/src/tools/identity-get-role-credentials.d.ts.map +1 -0
  90. package/dist/src/tools/identity-get-role-credentials.js +56 -0
  91. package/dist/src/tools/identity-get-session-token.d.ts +8 -0
  92. package/dist/src/tools/identity-get-session-token.d.ts.map +1 -0
  93. package/dist/src/tools/identity-get-session-token.js +46 -0
  94. package/dist/src/tools/identity-get-tip-token.d.ts +8 -0
  95. package/dist/src/tools/identity-get-tip-token.d.ts.map +1 -0
  96. package/dist/src/tools/identity-get-tip-token.js +46 -0
  97. package/dist/src/tools/identity-list-credentials.d.ts +2 -11
  98. package/dist/src/tools/identity-list-credentials.d.ts.map +1 -1
  99. package/dist/src/tools/identity-list-credentials.js +4 -3
  100. package/dist/src/tools/identity-list-risk-patterns.d.ts +2 -7
  101. package/dist/src/tools/identity-list-risk-patterns.d.ts.map +1 -1
  102. package/dist/src/tools/identity-list-roles.d.ts +8 -0
  103. package/dist/src/tools/identity-list-roles.d.ts.map +1 -0
  104. package/dist/src/tools/identity-list-roles.js +43 -0
  105. package/dist/src/tools/identity-list-tips.d.ts +2 -7
  106. package/dist/src/tools/identity-list-tips.d.ts.map +1 -1
  107. package/dist/src/tools/identity-login.d.ts +2 -7
  108. package/dist/src/tools/identity-login.d.ts.map +1 -1
  109. package/dist/src/tools/identity-logout.d.ts +2 -7
  110. package/dist/src/tools/identity-logout.d.ts.map +1 -1
  111. package/dist/src/tools/identity-risk-check.d.ts +3 -17
  112. package/dist/src/tools/identity-risk-check.d.ts.map +1 -1
  113. package/dist/src/tools/identity-set-binding.d.ts +2 -10
  114. package/dist/src/tools/identity-set-binding.d.ts.map +1 -1
  115. package/dist/src/tools/identity-status.d.ts +2 -7
  116. package/dist/src/tools/identity-status.d.ts.map +1 -1
  117. package/dist/src/tools/identity-unset-binding.d.ts +2 -9
  118. package/dist/src/tools/identity-unset-binding.d.ts.map +1 -1
  119. package/dist/src/tools/identity-whoami.d.ts +2 -7
  120. package/dist/src/tools/identity-whoami.d.ts.map +1 -1
  121. package/dist/src/types.d.ts +25 -0
  122. package/dist/src/types.d.ts.map +1 -1
  123. package/dist/src/utils/derive-session-key.d.ts +1 -0
  124. package/dist/src/utils/derive-session-key.d.ts.map +1 -1
  125. package/dist/src/utils/derive-session-key.js +28 -4
  126. package/dist/src/utils/resolve-identity-endpoint.d.ts +26 -0
  127. package/dist/src/utils/resolve-identity-endpoint.d.ts.map +1 -0
  128. package/dist/src/utils/resolve-identity-endpoint.js +90 -0
  129. package/openclaw.plugin.json +18 -1
  130. package/package.json +11 -3
  131. package/skills/SKILL.md +9 -9
package/README-cn.md CHANGED
@@ -39,6 +39,8 @@ UserPool OIDC 登录、TIP (Trusted Identity Provider) 令牌(通过 Identity
39
39
  | `list-tips` | 列出所有有效 TIP 令牌及其委托链、过期时间和环境变量绑定。 |
40
40
  | `config` | 显示 identity 插件配置(敏感信息脱敏)。 |
41
41
  | `list-credentials` 或 `list [page]` | 分页列出控制台 provider 及已绑定的凭据。使用 `list 2` 加载更多。 |
42
+ | `list-roles` | 列出 STS 角色类凭据提供方(非 OAuth/API key)。可选按名称前缀过滤。 |
43
+ | `get-role <provider> [--use-tip] [--show-secrets]` | 获取某角色提供方的 STS 临时凭据(默认脱敏)。 |
42
44
  | `fetch <provider> [--flow=...]` | 添加凭据。flow 根据 provider 类型自动推断;可用 `--flow` 覆盖。 |
43
45
  | `set <provider> <envVar>` | 将凭据绑定到环境变量供工具注入。无凭据时从 `process.env[envVar]` 导入。 |
44
46
  | `unset <provider>` | 移除 provider 的环境变量绑定。 |
@@ -104,7 +106,8 @@ openclaw plugins install --link .
104
106
 
105
107
  **A. 平台侧访问配置(Identity)**:用于获取 TIP Token、拉取/托管凭据、做权限校验(可选)。
106
108
 
107
- - `endpoint`:Identity API 地址(例如 `https://id.cn-beijing.volcengineapi.com`)。不填时使用默认值。
109
+ - `endpoint`(可选):Identity API 根地址(例如 `https://id.cn-beijing.volcengineapi.com`)。**优先级最高**。
110
+ - `regionMetadataUrl`(可选):返回 **纯文本 region id**(如 `cn-beijing`)的 HTTP(S) URL。仅当 **未配置 `endpoint`** 时使用:客户端拼接 `https://id.{region}.volcengineapi.com`。单次请求约 10s 超时;失败或正文无效(如 `unknown`)时回退到 `https://id.cn-beijing.volcengineapi.com`。示例:`http://100.96.0.96/latest/region_id`(需网关能访问)。
108
111
  - `accessKeyId` / `secretAccessKey`:用于访问 Identity API。**可选**,可使用环境变量或凭据文件(见下)。
109
112
  - `workloadPoolName` / `workloadName`:用于签发 TIP Token。默认:`default`、`openclaw-agent`。
110
113
  - `audience` / `durationSeconds`:可选,令牌受众与有效期。
@@ -113,6 +116,10 @@ openclaw plugins install --link .
113
116
  - `roleTrn`:STS AssumeRole 的 Role TRN。设置后(且未设置 `workloadName`)不传 workload name,后端使用 roleName。优先级:`workloadName` > `roleTrn` > params。与 `credentialsMetadataUrl` 配合时用于 AssumeRole,或与显式 AK/SK 配合。
114
117
  - `sessionToken`:STS 会话令牌(或使用 `VOLCENGINE_SESSION_TOKEN` 环境变量)。
115
118
 
119
+ **Identity API 地址解析**:已配置 `endpoint` → 否则用 `regionMetadataUrl` 拉取 region 拼接 URL → 否则 `https://id.cn-beijing.volcengineapi.com`。**SigV4 签名用 region** 从解析后的主机名匹配 `id.{region}.volcengineapi.com` 推断;否则为 `cn-beijing`。
120
+
121
+ **工作负载池(凭据 / STS)**:`workloadPoolName`(默认 `default`)用于限定 `ListCredentialProviders`、`ListRoleCredentialProviders` 以及 `GetResourceOauth2Token`、`GetResourceApiKey`、`GetUserCredential`、`GetRoleCredentials` 等接口的 `PoolName`。若配置了 `userpool.userPoolName`,角色提供方列表还会在客户端按用户池再过滤。
122
+
116
123
  **凭据解析顺序**(AK/SK):1)显式 config → 2)环境变量(`VOLCENGINE_ACCESS_KEY`、`VOLCENGINE_SECRET_KEY`、`VOLCENGINE_SESSION_TOKEN`)→ 3)远程元数据(`credentialsMetadataUrl` + `roleTrn`,从完整 URL 拉取后做 AssumeRole;404 时回退)→ 4)凭据文件(config 的 `credentialsFile`,或 `VOLCENGINE_CREDENTIALS_FILE` 环境变量,或 `/var/run/secrets/iam/credential`)。凭据文件格式(VeFaaS):`access_key_id`、`secret_access_key`、`session_token`(可选)、`role_trn`(可选,用于 AssumeRole)。`RUNTIME_IAM_ROLE_TRN` 环境变量可在从文件加载时提供 role TRN。
117
124
 
118
125
  **B. 用户登录配置(UserPool / OIDC)**:用于 `/identity login` 的用户登录与会话建立。
@@ -121,6 +128,8 @@ openclaw plugins install --link .
121
128
  - `clientId` / `clientSecret`(动态模式下可自动解析)
122
129
  - `callbackUrl`:OpenClaw 网关对外可访问的回调地址,例如 `http://127.0.0.1:18789/identity/oauth/callback`
123
130
  - `scope`:一般包含 `openid profile email`
131
+ - `identityProvider`(可选):授权 URL 中 `identity_provider` 对应的 IdP 名称;不填则使用 `ListIdentityProviders` 返回的第一条。
132
+ - `useRelayCallback`(可选):经 UserPool relay / `redirect_relay_uri` 的 OIDC 回调流程。默认 false。
124
133
 
125
134
  **C. 权限校验与风险审批(AuthZ,可选)**:用于 TIP + CheckPermission + 风险评估与用户审批。各开关独立,无统一 `enable`。
126
135
 
@@ -182,7 +191,8 @@ openclaw plugins install --link .
182
191
 
183
192
  | 参数 | 类型 | 必填 | 含义 |
184
193
  |------|------|------|------|
185
- | `endpoint` | string | | Identity API 地址,如 `https://id.cn-beijing.volcengineapi.com` |
194
+ | `endpoint` | string | | Identity API 根地址。不填则通过 `regionMetadataUrl` 或默认 `https://id.cn-beijing.volcengineapi.com` |
195
+ | `regionMetadataUrl` | string | 否 | 返回纯文本 region 的 URL;在未配置 `endpoint` 时拼接 `https://id.{region}.volcengineapi.com` |
186
196
  | `accessKeyId` | string | 否* | 火山引擎 Access Key。不填时从 `VOLCENGINE_ACCESS_KEY` 或 `credentialsFile` 读取 |
187
197
  | `secretAccessKey` | string | 否* | 火山引擎 Secret Key。不填时从 `VOLCENGINE_SECRET_KEY` 或 `credentialsFile` 读取 |
188
198
  | `workloadPoolName` | string | 否 | 工作负载池名称,默认 `default` |
@@ -195,6 +205,7 @@ openclaw plugins install --link .
195
205
  | `sessionToken` | string | 否 | STS 临时会话令牌(或 `VOLCENGINE_SESSION_TOKEN`) |
196
206
  | `subagentTipPropagation` | boolean | 否 | 将 TIP 和 session 传播到子 agent。默认 false |
197
207
  | `webchatSessionExchange` | boolean | 否 | 启用 `identity.session.put` / `identity.session.get` gateway WS 方法供 webchat 客户端使用。默认 false |
208
+ | `personalSessionMode` | boolean | 否 | 个人/单用户模式:TIP、OIDC session、凭据仅存储在 `agent:main:main`(不做按发送者或 per-channel-peer 隔离)。子 agent 会话不变。默认 false;多租户或群聊共享场景勿开启。 |
198
209
 
199
210
  \* AK/SK 至少通过 `accessKeyId`+`secretAccessKey`、环境变量、`credentialsMetadataUrl`+`roleTrn` 或 `credentialsFile` 之一提供。
200
211
 
@@ -243,8 +254,8 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
243
254
 
244
255
  | 方法 | 参数 | 响应 | 描述 |
245
256
  | --- | --- | --- | --- |
246
- | `identity.session.put` | `{ sessionKey, idToken, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | 将 OIDC id_token 注入到插件 session。通过 `buildEffectiveSessionKey` 解析实际存储 key(与 hooks/commands 相同的隔离逻辑)。 |
247
- | `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey }` | 获取指定 session 已存储的 user token |
257
+ | `identity.session.put` | `{ sessionKey, idToken, refreshToken?, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | 将 OIDC id_token 注入到插件 session;可选传入 `refreshToken`(加密存储),用于静默续期。通过 `buildEffectiveSessionKey` 解析实际存储 key(与 hooks/commands 相同的隔离逻辑)。 |
258
+ | `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey, hasRefreshToken }` | 获取指定 session 已存储的 user token。`hasRefreshToken` 表示是否存有 refresh token;响应中不会返回 refresh token 明文。 |
248
259
 
249
260
  - `senderId` 默认值为 `"openclaw-control-ui"`。对于 main session,实际存储 key 为 `agent:main:main:user:<senderId>`。
250
261
  - `channel` 可选;当 session 来源于可发送消息的渠道(feishu、telegram 等)时传入,可启用 per-channel-peer key 提升。
@@ -264,7 +275,7 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
264
275
  **典型流程(BFF → webchat → plugin):**
265
276
 
266
277
  1. BFF 完成 3LO 登录并获取用户的 OIDC `id_token`
267
- 2. Webchat 客户端调用 `identity.session.put`,传入 session key 和 `id_token`
278
+ 2. Webchat 客户端调用 `identity.session.put`,传入 session key 和 `id_token`(若需静默续期,可一并传入 token 响应中的 `refresh_token` 作为 `refreshToken`)
268
279
  3. 插件校验 token,存储 session,并获取 TIP
269
280
  4. 后续该 session 中的 agent 运行拥有有效身份——无需手动登录
270
281
 
@@ -274,20 +285,22 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
274
285
 
275
286
  ## 工具
276
287
 
277
- - **identity_whoami** - 显示当前会话身份(sub、TIP 状态)
278
- - **identity_status** - 登录状态、凭据、绑定
279
- - **identity_login** - 启动 OIDC 登录或刷新 TIP
280
- - **identity_logout** - 清除 session 和 TIP
281
- - **identity_list_credentials** - 列出 provider 和凭据(分页)
282
- - **identity_list_tips** - 列出有效 TIP 令牌和绑定
283
- - **identity_config** - 显示插件配置(脱敏)
284
- - **identity_config_suggest** - 生成 openclaw.json 配置片段(intent、lang)
285
- - **identity_fetch** - 添加凭据(provider、flow?、redirectUrl?、scopes?)
286
- - **identity_set_binding** - 绑定 provider 环境变量
287
- - **identity_unset_binding** - 移除环境变量绑定
288
- - **identity_approve_tool** - 可选工具;按 approval_id 审批高风险工具调用。推荐用户使用 `/identity approve <id>`(仅人工;agent 不得自批)。
289
- - **identity_risk_check** - 诊断命令或工具调用的风险(command toolName+params)
290
- - **identity_list_risk_patterns** - 列出内置危险命令和敏感路径
288
+ 面向 Agent 的用法见 [`skills/SKILL.md`](skills/SKILL.md)。本插件注册的工具有:
289
+
290
+ - **identity_whoami** 会话身份(sub、TIP
291
+ - **identity_status** 登录、TIP、凭据、绑定
292
+ - **identity_login** / **identity_logout** OIDC 登录或刷新 TIP;清除会话
293
+ - **identity_list_credentials** OAuth/API key 类 provider 与已存凭据(支持 `page`、`name`、`flow`、`type` 过滤)
294
+ - **identity_list_roles** STS 角色类凭据提供方(`name` 前缀过滤)
295
+ - **identity_fetch** 添加凭据(`provider`、`flow`、`redirectUrl`、`scopes`、`returnValue`)
296
+ - **identity_get_role_credentials** 某角色提供方的 STS 临时凭据(`providerName`、`useTip`)
297
+ - **identity_get_tip_token** / **identity_get_session_token** 原始 TIP JWT 或会话 user token(进阶场景)
298
+ - **identity_config** 当前生效配置(脱敏)
299
+ - **identity_config_suggest** 可合并的配置片段(`intent`、`lang`)
300
+ - **identity_set_binding** / **identity_unset_binding** 工具注入用的环境变量绑定
301
+ - **identity_risk_check** / **identity_list_risk_patterns** 风险评估(可选插件能力)
302
+ - **identity_approve_tool** — 可选;**仅供人工审批** — 推荐 `/identity approve <id>`(模型不得自批)
303
+ - **identity_list_tips** — 所有有效 TIP 与绑定(运维 / 多会话排查)
291
304
 
292
305
  ## 钩子
293
306
 
package/README.md CHANGED
@@ -39,6 +39,8 @@ Single command `/identity` (alias `/id`) with subcommands. Default with no args:
39
39
  | `list-tips` | List all valid TIP tokens with delegation chain, expiry, and env bindings. |
40
40
  | `config` | Show identity plugin config (sensitive values redacted). |
41
41
  | `list-credentials` or `list [page]` | List providers from control plane (paginated) and your credentials with bound env. Use `list 2` to load more. |
42
+ | `list-roles` | List STS role credential providers (not OAuth/API key). Optional name prefix filter. |
43
+ | `get-role <provider> [--use-tip] [--show-secrets]` | Get temporary STS credentials for a role provider (masked by default). |
42
44
  | `fetch <provider> [--flow=...]` | Add credential. Flow auto-inferred from provider type (api_key/oauth2/m2m); override with `--flow`. |
43
45
  | `set <provider> <envVar>` | Bind credential to env var for tool injection. If no credential, import from `process.env[envVar]`. |
44
46
  | `unset <provider>` | Remove env binding for provider. |
@@ -104,7 +106,8 @@ The plugin typically needs three types of config:
104
106
 
105
107
  **A. Platform access (Identity)**: For TIP Token, credential fetch/hosting, and optional permission checks.
106
108
 
107
- - `endpoint`: Identity API URL (e.g. `https://id.cn-beijing.volcengineapi.com`). Default when omitted.
109
+ - `endpoint` (optional): Full Identity API base URL (e.g. `https://id.cn-beijing.volcengineapi.com`). **Highest priority** for the API host.
110
+ - `regionMetadataUrl` (optional): HTTP(S) URL that returns a **plain-text region id** (e.g. `cn-beijing`). Used only when `endpoint` is **unset**: the client builds `https://id.{region}.volcengineapi.com`. Request timeout ~10s; on failure or invalid body (e.g. `unknown`), falls back to `https://id.cn-beijing.volcengineapi.com`. Example metadata URL: `http://100.96.0.96/latest/region_id` (must be reachable from the gateway).
108
111
  - `accessKeyId` / `secretAccessKey`: For Identity API access. **Optional** when using env vars or credential file (see below).
109
112
  - `workloadPoolName` / `workloadName`: For issuing TIP Token. Defaults: `default`, `openclaw-agent`.
110
113
  - `audience` / `durationSeconds`: Optional, token audience and validity.
@@ -113,6 +116,10 @@ The plugin typically needs three types of config:
113
116
  - `roleTrn`: Role TRN for STS AssumeRole. When set (and `workloadName` not set), workload name is omitted; backend uses roleName. Priority: `workloadName` > `roleTrn` > params. Used with `credentialsMetadataUrl` (AssumeRole after fetch) or explicit AK/SK.
114
117
  - `sessionToken`: STS session token (or use `VOLCENGINE_SESSION_TOKEN` env).
115
118
 
119
+ **Identity API host resolution**: `endpoint` if set → else region from `regionMetadataUrl` → else `https://id.cn-beijing.volcengineapi.com`. **SigV4 signing region** is inferred from the resolved host when it matches `id.{region}.volcengineapi.com`; otherwise `cn-beijing`.
120
+
121
+ **Workload pool (credentials / STS)**: `workloadPoolName` (default `default`) scopes `ListCredentialProviders`, `ListRoleCredentialProviders`, and control-plane calls such as `GetResourceOauth2Token`, `GetResourceApiKey`, `GetUserCredential`, and `GetRoleCredentials` via `PoolName`. Role provider listing also filters by `userpool.userPoolName` when configured.
122
+
116
123
  **Credential resolution order** (AK/SK): 1) Explicit config → 2) Env vars (`VOLCENGINE_ACCESS_KEY`, `VOLCENGINE_SECRET_KEY`, `VOLCENGINE_SESSION_TOKEN`) → 3) Remote metadata (`credentialsMetadataUrl` + `roleTrn`, fetches from full URL then AssumeRole; 404 falls through) → 4) Credential file (`credentialsFile` config, or `VOLCENGINE_CREDENTIALS_FILE` env, or `/var/run/secrets/iam/credential`). Credential file format (VeFaaS): `access_key_id`, `secret_access_key`, `session_token` (optional), `role_trn` (optional for AssumeRole). `RUNTIME_IAM_ROLE_TRN` env can supply role TRN when loading from file.
117
124
 
118
125
  **B. User login (UserPool / OIDC)**: For `/identity login` and session setup.
@@ -121,6 +128,8 @@ The plugin typically needs three types of config:
121
128
  - `clientId` / `clientSecret` (auto-resolved in dynamic mode)
122
129
  - `callbackUrl`: Public callback URL for OpenClaw gateway, e.g. `http://127.0.0.1:18789/identity/oauth/callback`
123
130
  - `scope`: Typically `openid profile email`
131
+ - `identityProvider` (optional): IdP name for the `identity_provider` authorize param. When omitted, the first entry from `ListIdentityProviders` is used.
132
+ - `useRelayCallback` (optional): UserPool relay / `redirect_relay_uri` flow for OIDC callback. Default false.
124
133
 
125
134
  **C. AuthZ and risk approval (optional)**: For TIP + CheckPermission + risk evaluation. Each flag is independent; no single "enable" switch.
126
135
 
@@ -182,7 +191,8 @@ Add to `openclaw.json` under `plugins.entries.agent-identity.config`:
182
191
 
183
192
  | Param | Type | Required | Description |
184
193
  |-------|------|----------|--------------|
185
- | `endpoint` | string | Yes | Identity API URL, e.g. `https://id.cn-beijing.volcengineapi.com` |
194
+ | `endpoint` | string | No | Identity API base URL. Omit to use `regionMetadataUrl` or default `https://id.cn-beijing.volcengineapi.com` |
195
+ | `regionMetadataUrl` | string | No | Plain-text region id URL; builds `https://id.{region}.volcengineapi.com` when `endpoint` unset |
186
196
  | `accessKeyId` | string | No* | Volcengine Access Key. Omit to load from `VOLCENGINE_ACCESS_KEY` or `credentialsFile` |
187
197
  | `secretAccessKey` | string | No* | Volcengine Secret Key. Omit to load from `VOLCENGINE_SECRET_KEY` or `credentialsFile` |
188
198
  | `workloadPoolName` | string | No | Workload pool name, default `default` |
@@ -195,6 +205,7 @@ Add to `openclaw.json` under `plugins.entries.agent-identity.config`:
195
205
  | `sessionToken` | string | No | STS session token (or `VOLCENGINE_SESSION_TOKEN`) |
196
206
  | `subagentTipPropagation` | boolean | No | Propagate TIP and session to subagents. Default false |
197
207
  | `webchatSessionExchange` | boolean | No | Enable `identity.session.put` / `identity.session.get` gateway WS methods for webchat clients. Default false |
208
+ | `personalSessionMode` | boolean | No | Single-user mode: TIP, OIDC session, and credentials are stored only under `agent:main:main` (no per-sender or per-channel-peer keys). Subagent sessions unchanged. Default false — do not enable for multi-tenant or shared groups. |
198
209
 
199
210
  \* AK/SK must be provided via `accessKeyId`+`secretAccessKey`, environment variables, `credentialsMetadataUrl`+`roleTrn`, or `credentialsFile`.
200
211
 
@@ -243,8 +254,8 @@ When `identity.webchatSessionExchange` is `true`, the plugin registers two gatew
243
254
 
244
255
  | Method | Params | Response | Description |
245
256
  | --- | --- | --- | --- |
246
- | `identity.session.put` | `{ sessionKey, idToken, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | Inject an OIDC id_token into a plugin session. Resolves effective storage key via `buildEffectiveSessionKey` (same sender isolation as hooks/commands). |
247
- | `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey }` | Retrieve the stored user token for a session. |
257
+ | `identity.session.put` | `{ sessionKey, idToken, refreshToken?, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | Inject an OIDC id_token into a plugin session; optional `refreshToken` is stored encrypted for silent token renewal. Resolves effective storage key via `buildEffectiveSessionKey` (same sender isolation as hooks/commands). |
258
+ | `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey, hasRefreshToken }` | Retrieve the stored user token for a session. `hasRefreshToken` indicates whether a refresh token is stored; the refresh token value is never returned. |
248
259
 
249
260
  - `senderId` defaults to `"openclaw-control-ui"`. The effective storage key is `agent:main:main:user:<senderId>` for main sessions.
250
261
  - `channel` is optional; when the session originates from a sendable channel (feishu, telegram, etc.), pass it to enable per-channel-peer key promotion.
@@ -264,7 +275,7 @@ Both methods are **restricted to webchat WS connections only** (`isWebchatConnec
264
275
  **Typical flow (BFF → webchat → plugin):**
265
276
 
266
277
  1. BFF completes 3LO login and obtains an OIDC `id_token` for the user
267
- 2. Webchat client calls `identity.session.put` with the session key and `id_token`
278
+ 2. Webchat client calls `identity.session.put` with the session key and `id_token` (optionally `refreshToken` from the token response if silent renewal is desired)
268
279
  3. Plugin verifies the token, stores the session, and acquires TIP
269
280
  4. Subsequent agent runs in that session have a valid identity — no manual login needed
270
281
 
@@ -274,20 +285,22 @@ Follow-up messages (login success, credential fetch done) are not delivered when
274
285
 
275
286
  ## Tools
276
287
 
277
- - **identity_whoami** - Show current session identity (sub, TIP status)
278
- - **identity_status** - Login status, credentials, bindings
279
- - **identity_login** - Start OIDC login or refresh TIP
280
- - **identity_logout** - Clear session and TIP
281
- - **identity_list_credentials** - List providers and credentials (paginated)
282
- - **identity_list_tips** - List valid TIP tokens and bindings
283
- - **identity_config** - Show plugin config (redacted)
284
- - **identity_config_suggest** - Generate config snippets for openclaw.json (intent, lang)
285
- - **identity_fetch** - Add credential (provider, flow?, redirectUrl?, scopes?)
286
- - **identity_set_binding** - Bind provider env var
287
- - **identity_unset_binding** - Remove env binding
288
- - **identity_approve_tool** - Optional tool; approve high-risk tool call by approval_id. Prefer `/identity approve <id>` (human-only; agent must not self-approve).
289
- - **identity_risk_check** - Diagnose risk for a command or tool call (command, or toolName+params)
290
- - **identity_list_risk_patterns** - List built-in dangerous commands and sensitive paths
288
+ Agent-facing behavior is summarized in [`skills/SKILL.md`](skills/SKILL.md). Registered tools:
289
+
290
+ - **identity_whoami** Session identity (sub, TIP)
291
+ - **identity_status** Login, TIP, credentials, bindings
292
+ - **identity_login** / **identity_logout** OIDC login or refresh TIP; clear session
293
+ - **identity_list_credentials** OAuth/API key providers and stored credentials (`page`, `name`, `flow`, `type` filters)
294
+ - **identity_list_roles** STS role credential providers (`name` prefix filter)
295
+ - **identity_fetch** Add credential (`provider`, `flow`, `redirectUrl`, `scopes`, `returnValue`)
296
+ - **identity_get_role_credentials** STS credentials for a role provider (`providerName`, `useTip`)
297
+ - **identity_get_tip_token** / **identity_get_session_token** Raw TIP JWT or session user token (advanced)
298
+ - **identity_config** Effective plugin config (redacted)
299
+ - **identity_config_suggest** Config merge snippets (`intent`, `lang`)
300
+ - **identity_set_binding** / **identity_unset_binding** Env var bindings for tool injection
301
+ - **identity_risk_check** / **identity_list_risk_patterns** Risk evaluation (optional plugin)
302
+ - **identity_approve_tool** — Optional; **human approval only** — prefer `/identity approve <id>` (agents must not self-approve)
303
+ - **identity_list_tips** — All valid TIP tokens and bindings (ops / multi-session debug)
291
304
 
292
305
  ## Hooks
293
306
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA0E7D,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QAyatD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAmF7D,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QA+etD"}
package/dist/index.js CHANGED
@@ -13,15 +13,18 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { runPluginPreflight } from "./src/preflight/plugin-preflight.js";
17
+ import { pluginState } from "./src/preflight/plugin-state.js";
16
18
  import { createIdentityCommand, createIdCommand } from "./src/commands/identity-commands.js";
17
19
  import { createBeforeAgentStartHandler } from "./src/hooks/before-agent-start.js";
18
20
  import { createLlmInputHandler } from "./src/hooks/llm-input.js";
19
21
  import { createSessionsSendPropagationHandler } from "./src/hooks/sessions-send-propagation.js";
20
22
  import { createSessionsSpawnPropagationHandler } from "./src/hooks/sessions-spawn-propagation.js";
21
23
  import { createSubagentEndedCleanupHandler } from "./src/hooks/subagent-ended-cleanup.js";
22
- import { setSender, clearSender } from "./src/store/sender-session-store.js";
24
+ import { setSender, clearSender, setPersonalSessionMode } from "./src/store/sender-session-store.js";
23
25
  import { deriveSessionKey, needsSenderIsolation, } from "./src/utils/derive-session-key.js";
24
26
  import { createBeforeToolCallHandler } from "./src/hooks/before-tool-call.js";
27
+ import { createToolResultPersistHandler } from "./src/hooks/tool-result-persist.js";
25
28
  import { createAfterToolCallHandler } from "./src/hooks/after-tool-call.js";
26
29
  import * as skillPathStore from "./src/store/skill-path-store.js";
27
30
  import { createOIDCCallbackHandler, createOIDCCallbackHandlerLazy, } from "./src/routes/oidc-login.js";
@@ -34,7 +37,11 @@ import { createIdentityConfigSuggestTool } from "./src/tools/identity-config-sug
34
37
  import { createIdentityListRiskPatternsTool } from "./src/tools/identity-list-risk-patterns.js";
35
38
  import { createIdentityRiskCheckTool } from "./src/tools/identity-risk-check.js";
36
39
  import { createIdentityFetchTool } from "./src/tools/identity-fetch.js";
40
+ import { createIdentityGetRoleCredentialsTool } from "./src/tools/identity-get-role-credentials.js";
41
+ import { createIdentityGetTipTokenTool } from "./src/tools/identity-get-tip-token.js";
42
+ import { createIdentityGetSessionTokenTool } from "./src/tools/identity-get-session-token.js";
37
43
  import { createIdentityListCredentialsTool } from "./src/tools/identity-list-credentials.js";
44
+ import { createIdentityListRolesTool } from "./src/tools/identity-list-roles.js";
38
45
  import { createIdentityListTipsTool } from "./src/tools/identity-list-tips.js";
39
46
  import { createIdentityLoginTool } from "./src/tools/identity-login.js";
40
47
  import { createIdentityLogoutTool } from "./src/tools/identity-logout.js";
@@ -54,6 +61,7 @@ function hasAnyIdentityConfig(identity) {
54
61
  if (!identity)
55
62
  return false;
56
63
  return Boolean(identity.endpoint ||
64
+ identity.regionMetadataUrl ||
57
65
  identity.accessKeyId ||
58
66
  identity.secretAccessKey ||
59
67
  identity.sessionToken ||
@@ -70,11 +78,16 @@ export default function register(api) {
70
78
  const storeDir = api.resolvePath(PLUGIN_STORE_DIR);
71
79
  initEncryptionKey(storeDir);
72
80
  const identityCfg = pluginConfig.identity;
81
+ setPersonalSessionMode(identityCfg?.personalSessionMode === true);
82
+ if (identityCfg?.personalSessionMode) {
83
+ logInfo(api.logger, "identity.personalSessionMode: non-subagent TIP/session/credentials use agent:main:main only");
84
+ }
73
85
  const hasIdentity = hasAnyIdentityConfig(identityCfg);
74
86
  const userpool = pluginConfig.userpool;
75
87
  const identityClient = hasIdentity
76
88
  ? new IdentityClient({
77
- endpoint: identityCfg?.endpoint ?? "https://id.cn-beijing.volcengineapi.com",
89
+ endpoint: identityCfg?.endpoint,
90
+ regionMetadataUrl: identityCfg?.regionMetadataUrl,
78
91
  accessKeyId: identityCfg?.accessKeyId,
79
92
  secretAccessKey: identityCfg?.secretAccessKey,
80
93
  sessionToken: identityCfg?.sessionToken,
@@ -96,6 +109,9 @@ export default function register(api) {
96
109
  getResourceApiKey: async () => {
97
110
  throw new Error("Identity not configured.");
98
111
  },
112
+ getUserCredential: async () => {
113
+ throw new Error("Identity not configured.");
114
+ },
99
115
  checkPermission: async () => {
100
116
  throw new Error("Identity not configured.");
101
117
  },
@@ -106,9 +122,24 @@ export default function register(api) {
106
122
  PageNumber: 1,
107
123
  PageSize: 20,
108
124
  }),
125
+ listRoleCredentialProviders: async () => ({
126
+ RoleCredentialProviders: [],
127
+ TotalCount: 0,
128
+ PageNumber: 1,
129
+ PageSize: 20,
130
+ }),
131
+ getRoleCredentials: async () => {
132
+ throw new Error("Identity not configured.");
133
+ },
109
134
  getUserPool: async () => {
110
135
  throw new Error("Identity not configured.");
111
136
  },
137
+ listIdentityProviders: async () => ({
138
+ pageNumber: 1,
139
+ pageSize: 10,
140
+ totalCount: 0,
141
+ data: [],
142
+ }),
112
143
  listUserPools: async () => ({
113
144
  pageNumber: 1,
114
145
  pageSize: 10,
@@ -278,23 +309,29 @@ export default function register(api) {
278
309
  getOidcConfigForRefresh: getOidcConfigForRefresh ?? undefined,
279
310
  configWorkloadName: identityCfg?.workloadName,
280
311
  identityClient: hasIdentity ? identityClient : undefined,
312
+ workloadPoolName: identityCfg?.workloadPoolName ?? "default",
313
+ userPoolName: userpool?.userPoolName,
281
314
  logger: api.logger,
282
315
  pluginConfig,
283
316
  sendCredentialMessage: sendToSession,
284
317
  };
285
318
  api.registerCommand(createIdentityCommand(identityCommandsDeps));
286
319
  api.registerCommand(createIdCommand(identityCommandsDeps));
287
- logInfo(api.logger, "commands /identity, /id (login, status, logout, list-tips, list-credentials, fetch, set, unset); HTTP callback /identity/oauth/callback (credential OAuth uses Identity callback)");
320
+ logInfo(api.logger, "commands /identity, /id (login, status, logout, list, list-roles, list-tips, fetch, set, unset); HTTP callback /identity/oauth/callback (credential OAuth uses Identity callback)");
288
321
  // Tools (share deps with commands). Optional = only included when agent allowlist explicitly adds them.
289
322
  api.registerTool(createIdentityWhoamiTool(identityCommandsDeps), { optional: false });
290
323
  api.registerTool(createIdentityLogoutTool(identityCommandsDeps), { optional: false });
291
324
  api.registerTool(createIdentityStatusTool(identityCommandsDeps), { optional: false });
292
325
  api.registerTool(createIdentityLoginTool(identityCommandsDeps), { optional: false });
293
326
  api.registerTool(createIdentityListCredentialsTool(identityCommandsDeps), { optional: false });
327
+ api.registerTool(createIdentityListRolesTool(identityCommandsDeps), { optional: false });
294
328
  api.registerTool(createIdentityListTipsTool(identityCommandsDeps), { optional: false });
295
329
  api.registerTool(createIdentityConfigTool(identityCommandsDeps), { optional: false });
296
330
  api.registerTool(createIdentityConfigSuggestTool(), { optional: false });
297
331
  api.registerTool(createIdentityFetchTool(identityCommandsDeps), { optional: false });
332
+ api.registerTool(createIdentityGetRoleCredentialsTool(identityCommandsDeps), { optional: false });
333
+ api.registerTool(createIdentityGetTipTokenTool(identityCommandsDeps), { optional: false });
334
+ api.registerTool(createIdentityGetSessionTokenTool(identityCommandsDeps), { optional: false });
298
335
  api.registerTool(createIdentitySetBindingTool(identityCommandsDeps), { optional: true });
299
336
  api.registerTool(createIdentityUnsetBindingTool(identityCommandsDeps), { optional: true });
300
337
  api.registerTool(createIdentityRiskCheckTool({ pluginConfig, logger: api.logger }), { optional: true });
@@ -391,12 +428,12 @@ export default function register(api) {
391
428
  logger: api.logger,
392
429
  }));
393
430
  if (skillReadCheck) {
394
- api.on("session_end", (_event, ctx) => {
395
- if (ctx.sessionId)
396
- skillPathStore.clearSessionById(ctx.sessionId);
431
+ api.on("session_end", (event) => {
432
+ if (event.sessionId)
433
+ skillPathStore.clearSessionById(event.sessionId);
397
434
  });
398
435
  }
399
- // before_tool_call: authz, credential injection, group sender context
436
+ // before_tool_call: authz, credential injection, group sender context, contract injection
400
437
  api.on("before_tool_call", createBeforeToolCallHandler({
401
438
  storeDir,
402
439
  identityClient: hasIdentity ? identityClient : undefined,
@@ -408,9 +445,11 @@ export default function register(api) {
408
445
  identityService: hasIdentity ? identityService : undefined,
409
446
  getOidcConfigForRefresh: getOidcConfigForRefresh ?? undefined,
410
447
  configWorkloadName: identityCfg?.workloadName,
448
+ workspaceDir: api.resolvePath?.(".") ?? undefined,
411
449
  }));
412
450
  // Companion after_tool_call: restore env snapshot set by credential injection
413
451
  api.on("after_tool_call", createAfterToolCallHandler({ logger: api.logger }));
452
+ api.on("tool_result_persist", createToolResultPersistHandler({ logger: api.logger }));
414
453
  // Gateway WS methods: webchat session exchange (inject / retrieve user token)
415
454
  if (identityCfg?.webchatSessionExchange && hasIdentity) {
416
455
  const sessionMethodDeps = {
@@ -424,4 +463,38 @@ export default function register(api) {
424
463
  api.registerGatewayMethod("identity.session.get", createSessionGetHandler(sessionMethodDeps));
425
464
  logInfo(api.logger, "gateway methods: identity.session.put, identity.session.get (webchat session exchange)");
426
465
  }
466
+ // Preflight: run async after register() returns so startup is never blocked.
467
+ // On any failure, set pluginState.degraded so hooks skip all interception.
468
+ const authzEnabled = !!(authz?.agentCheck || authz?.toolCheck || authz?.requireRiskApproval);
469
+ runPluginPreflight({
470
+ identityClient,
471
+ identityService,
472
+ hasIdentity,
473
+ credentialConfig: identityCfg
474
+ ? {
475
+ accessKeyId: identityCfg.accessKeyId,
476
+ secretAccessKey: identityCfg.secretAccessKey,
477
+ sessionToken: identityCfg.sessionToken,
478
+ credentialsFile: identityCfg.credentialsFile,
479
+ credentialsMetadataUrl: identityCfg.credentialsMetadataUrl,
480
+ roleTrn: identityCfg.roleTrn,
481
+ }
482
+ : undefined,
483
+ userpool: dynamicOidcEnabled
484
+ ? { mode: "dynamic", userPoolName: userpool?.userPoolName }
485
+ : explicitOidcEnabled
486
+ ? { mode: "explicit", discoveryUrl: userpool?.discoveryUrl }
487
+ : undefined,
488
+ workloadPoolName: identityCfg?.workloadPoolName,
489
+ authzEnabled,
490
+ namespaceName: authz?.namespaceName ?? "default",
491
+ logger: api.logger,
492
+ }).then((result) => {
493
+ if (!result.ok) {
494
+ pluginState.degraded = true;
495
+ pluginState.failures = result.failures;
496
+ }
497
+ }).catch((err) => {
498
+ logWarn(api.logger, `[identity] preflight threw unexpectedly: ${String(err)}`);
499
+ });
427
500
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Demo: read local sessions.json (with field-level decryption), resolve one sessionKey, print userToken.
3
+ *
4
+ * Same path as the plugin: initEncryptionKey(storeDir) then getSession(storeDir, sessionKey).
5
+ *
6
+ * Usage (after `pnpm build`):
7
+ * node dist/scripts/demo-get-session.js <sessionKey>
8
+ * node dist/scripts/demo-get-session.js <storeDir> <sessionKey>
9
+ * pnpm demo:get-session -- <sessionKey>
10
+ *
11
+ * Flags:
12
+ * --print-token Print full userToken (default: only prefix + length)
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=demo-get-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo-get-session.d.ts","sourceRoot":"","sources":["../../scripts/demo-get-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Demo: read local sessions.json (with field-level decryption), resolve one sessionKey, print userToken.
3
+ *
4
+ * Same path as the plugin: initEncryptionKey(storeDir) then getSession(storeDir, sessionKey).
5
+ *
6
+ * Usage (after `pnpm build`):
7
+ * node dist/scripts/demo-get-session.js <sessionKey>
8
+ * node dist/scripts/demo-get-session.js <storeDir> <sessionKey>
9
+ * pnpm demo:get-session -- <sessionKey>
10
+ *
11
+ * Flags:
12
+ * --print-token Print full userToken (default: only prefix + length)
13
+ */
14
+ import path from "node:path";
15
+ import os from "node:os";
16
+ import { initEncryptionKey } from "../src/store/encryption.js";
17
+ import { getSession } from "../src/store/session-store.js";
18
+ function usage() {
19
+ console.error(`Usage: demo-get-session [--print-token] <sessionKey>
20
+ demo-get-session [--print-token] <storeDir> <sessionKey>
21
+
22
+ storeDir defaults to ~/.openclaw/plugins/identity`);
23
+ process.exit(1);
24
+ }
25
+ async function main() {
26
+ const printToken = process.argv.includes("--print-token");
27
+ const args = process.argv.slice(2).filter((a) => a !== "--print-token");
28
+ if (args.length < 1 || args.length > 2)
29
+ usage();
30
+ const storeDir = args.length === 2
31
+ ? path.resolve(args[0])
32
+ : path.join(os.homedir(), ".openclaw", "plugins", "identity");
33
+ const sessionKey = args.length === 2 ? args[1] : args[0];
34
+ initEncryptionKey(storeDir);
35
+ const session = await getSession(storeDir, sessionKey);
36
+ if (!session) {
37
+ console.log(JSON.stringify({ ok: false, reason: "no session or expired", storeDir, sessionKey }, null, 2));
38
+ process.exit(2);
39
+ }
40
+ const tokenPreview = printToken
41
+ ? session.userToken
42
+ : `${session.userToken.slice(0, 12)}… (${session.userToken.length} chars)`;
43
+ console.log(JSON.stringify({
44
+ ok: true,
45
+ storeDir,
46
+ sessionKey,
47
+ sub: session.sub,
48
+ loginAt: session.loginAt,
49
+ expiresAt: session.expiresAt ?? null,
50
+ hasRefreshToken: Boolean(session.refreshToken),
51
+ claims: session.claims ?? null,
52
+ userToken: tokenPreview,
53
+ }, null, 2));
54
+ }
55
+ main().catch((err) => {
56
+ console.error(err);
57
+ process.exit(1);
58
+ });
@@ -15,6 +15,10 @@ export type OIDCConfigForCommand = {
15
15
  clientSecret?: string;
16
16
  scope?: string;
17
17
  callbackUrl: string;
18
+ /** UserPool UID (available when resolved dynamically via resolveOIDCConfig). */
19
+ poolUid?: string;
20
+ /** First identity provider cached at config resolve time. */
21
+ identityProvider?: string;
18
22
  };
19
23
  export type IdentityActionsLogger = {
20
24
  info?: (msg: string) => void;
@@ -28,11 +32,13 @@ export type IdentityActionsDeps = {
28
32
  getOidcConfigForRefresh?: () => Promise<OIDCConfigForRefresh>;
29
33
  configWorkloadName?: string;
30
34
  identityClient?: IdentityClientInterface;
35
+ workloadPoolName?: string;
36
+ userPoolName?: string;
31
37
  logger?: IdentityActionsLogger;
32
38
  pluginConfig?: PluginConfig;
33
39
  sendCredentialMessage?: (targetOrSessionKey: SessionKeyDeliveryTarget | string, text: string) => Promise<void>;
34
40
  };
35
- export type FetchFlow = "oauth2-user" | "oauth2-m2m" | "apikey";
41
+ export type FetchFlow = "oauth2-user" | "oauth2-m2m" | "apikey" | "user";
36
42
  export type StatusResult = {
37
43
  loggedIn: boolean;
38
44
  sub: string | null;
@@ -69,14 +75,15 @@ export type LogoutResult = {
69
75
  ok: boolean;
70
76
  };
71
77
  export declare function runLogout(deps: IdentityActionsDeps, sessionKey: string): Promise<LogoutResult>;
78
+ export type ProviderRow = {
79
+ name: string;
80
+ type: string;
81
+ flow?: string;
82
+ status: string;
83
+ binding?: string;
84
+ };
72
85
  export type ListCredentialsResult = {
73
- providers: Array<{
74
- name: string;
75
- type: string;
76
- flow?: string;
77
- status: string;
78
- binding?: string;
79
- }>;
86
+ providers: ProviderRow[];
80
87
  storedOnly: Array<{
81
88
  name: string;
82
89
  status: string;
@@ -89,8 +96,21 @@ export type ListCredentialsResult = {
89
96
  export type ListCredentialsFilter = {
90
97
  name?: string;
91
98
  flow?: string;
99
+ type?: string;
92
100
  };
93
101
  export declare function runListCredentials(deps: IdentityActionsDeps, sessionKey: string, page?: number, filter?: ListCredentialsFilter): Promise<ListCredentialsResult>;
102
+ export type RoleProviderRow = {
103
+ name: string;
104
+ identitySource?: string;
105
+ };
106
+ export type ListRoleCredentialsResult = {
107
+ providers: RoleProviderRow[];
108
+ page: number;
109
+ hasMore: boolean;
110
+ };
111
+ export declare function runListRoleCredentials(deps: IdentityActionsDeps, sessionKey: string, filter?: {
112
+ name?: string;
113
+ }): Promise<ListRoleCredentialsResult>;
94
114
  export type ListTipsResult = {
95
115
  tips: Array<{
96
116
  sessionKey: string;
@@ -148,4 +168,50 @@ export type UnsetBindingResult = {
148
168
  export declare function runUnsetBinding(deps: IdentityActionsDeps, sessionKey: string, params: {
149
169
  provider: string;
150
170
  }): Promise<UnsetBindingResult>;
171
+ export type GetRoleCredentialsActionResult = {
172
+ kind: "success";
173
+ credentials: {
174
+ AccessKeyId: string;
175
+ SecretAccessKey: string;
176
+ SessionToken: string;
177
+ Expiration?: string;
178
+ };
179
+ } | {
180
+ kind: "error";
181
+ message: string;
182
+ };
183
+ export declare function runGetRoleCredentials(deps: IdentityActionsDeps, sessionKey: string, params: {
184
+ providerName: string;
185
+ useTip?: boolean;
186
+ config?: import("openclaw/plugin-sdk").OpenClawConfig;
187
+ }): Promise<GetRoleCredentialsActionResult>;
188
+ export type GetTipTokenResult = {
189
+ kind: "success";
190
+ tipToken: string;
191
+ sub: string;
192
+ issuedAt: number;
193
+ expiresAt: number;
194
+ } | {
195
+ kind: "error";
196
+ message: string;
197
+ };
198
+ /**
199
+ * Return the current TIP JWT for the session (refresh/obtain via user token if needed).
200
+ */
201
+ export declare function runGetTipToken(deps: IdentityActionsDeps, sessionKey: string, config?: OpenClawConfig): Promise<GetTipTokenResult>;
202
+ export type GetSessionTokenResult = {
203
+ kind: "success";
204
+ /** OIDC id_token stored for the session. */
205
+ sessionIdToken: string;
206
+ sub: string;
207
+ loginAt: number;
208
+ expiresAt?: number;
209
+ } | {
210
+ kind: "error";
211
+ message: string;
212
+ };
213
+ /**
214
+ * Return the OIDC id_token (user / session identity token) for the session.
215
+ */
216
+ export declare function runGetSessionToken(deps: IdentityActionsDeps, sessionKey: string): Promise<GetSessionTokenResult>;
151
217
  //# sourceMappingURL=identity-actions.d.ts.map