@m1a0rz/agent-identity 0.1.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.
Files changed (125) hide show
  1. package/README-cn.md +223 -0
  2. package/README.md +223 -0
  3. package/dist/index.d.ts +14 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +306 -0
  6. package/dist/src/actions/identity-actions.d.ts +142 -0
  7. package/dist/src/actions/identity-actions.d.ts.map +1 -0
  8. package/dist/src/actions/identity-actions.js +429 -0
  9. package/dist/src/commands/identity-commands.d.ts +33 -0
  10. package/dist/src/commands/identity-commands.d.ts.map +1 -0
  11. package/dist/src/commands/identity-commands.js +572 -0
  12. package/dist/src/hooks/after-tool-call.d.ts +22 -0
  13. package/dist/src/hooks/after-tool-call.d.ts.map +1 -0
  14. package/dist/src/hooks/after-tool-call.js +35 -0
  15. package/dist/src/hooks/before-agent-start.d.ts +30 -0
  16. package/dist/src/hooks/before-agent-start.d.ts.map +1 -0
  17. package/dist/src/hooks/before-agent-start.js +93 -0
  18. package/dist/src/hooks/before-tool-call.d.ts +38 -0
  19. package/dist/src/hooks/before-tool-call.d.ts.map +1 -0
  20. package/dist/src/hooks/before-tool-call.js +138 -0
  21. package/dist/src/risk/classify-risk.d.ts +24 -0
  22. package/dist/src/risk/classify-risk.d.ts.map +1 -0
  23. package/dist/src/risk/classify-risk.js +61 -0
  24. package/dist/src/risk/diagnose-risk.d.ts +21 -0
  25. package/dist/src/risk/diagnose-risk.d.ts.map +1 -0
  26. package/dist/src/risk/diagnose-risk.js +37 -0
  27. package/dist/src/risk/llm-risk-check.d.ts +27 -0
  28. package/dist/src/risk/llm-risk-check.d.ts.map +1 -0
  29. package/dist/src/risk/llm-risk-check.js +274 -0
  30. package/dist/src/risk/low-risk-tools.d.ts +5 -0
  31. package/dist/src/risk/low-risk-tools.d.ts.map +1 -0
  32. package/dist/src/risk/low-risk-tools.js +29 -0
  33. package/dist/src/routes/oidc-login.d.ts +51 -0
  34. package/dist/src/routes/oidc-login.d.ts.map +1 -0
  35. package/dist/src/routes/oidc-login.js +153 -0
  36. package/dist/src/services/identity-client.d.ts +366 -0
  37. package/dist/src/services/identity-client.d.ts.map +1 -0
  38. package/dist/src/services/identity-client.js +578 -0
  39. package/dist/src/services/identity-credentials.d.ts +28 -0
  40. package/dist/src/services/identity-credentials.d.ts.map +1 -0
  41. package/dist/src/services/identity-credentials.js +170 -0
  42. package/dist/src/services/identity-service.d.ts +33 -0
  43. package/dist/src/services/identity-service.d.ts.map +1 -0
  44. package/dist/src/services/identity-service.js +53 -0
  45. package/dist/src/services/oidc-client.d.ts +57 -0
  46. package/dist/src/services/oidc-client.d.ts.map +1 -0
  47. package/dist/src/services/oidc-client.js +127 -0
  48. package/dist/src/services/send-notification-feishu.d.ts +27 -0
  49. package/dist/src/services/send-notification-feishu.d.ts.map +1 -0
  50. package/dist/src/services/send-notification-feishu.js +148 -0
  51. package/dist/src/services/session-refresh.d.ts +16 -0
  52. package/dist/src/services/session-refresh.d.ts.map +1 -0
  53. package/dist/src/services/session-refresh.js +38 -0
  54. package/dist/src/store/credential-env-bindings.d.ts +16 -0
  55. package/dist/src/store/credential-env-bindings.d.ts.map +1 -0
  56. package/dist/src/store/credential-env-bindings.js +61 -0
  57. package/dist/src/store/credential-store.d.ts +31 -0
  58. package/dist/src/store/credential-store.d.ts.map +1 -0
  59. package/dist/src/store/credential-store.js +57 -0
  60. package/dist/src/store/oidc-state-store.d.ts +15 -0
  61. package/dist/src/store/oidc-state-store.d.ts.map +1 -0
  62. package/dist/src/store/oidc-state-store.js +32 -0
  63. package/dist/src/store/session-store.d.ts +21 -0
  64. package/dist/src/store/session-store.d.ts.map +1 -0
  65. package/dist/src/store/session-store.js +69 -0
  66. package/dist/src/store/tip-store.d.ts +21 -0
  67. package/dist/src/store/tip-store.d.ts.map +1 -0
  68. package/dist/src/store/tip-store.js +60 -0
  69. package/dist/src/store/tool-approval-store.d.ts +44 -0
  70. package/dist/src/store/tool-approval-store.d.ts.map +1 -0
  71. package/dist/src/store/tool-approval-store.js +147 -0
  72. package/dist/src/tools/identity-approve-tool.d.ts +24 -0
  73. package/dist/src/tools/identity-approve-tool.d.ts.map +1 -0
  74. package/dist/src/tools/identity-approve-tool.js +36 -0
  75. package/dist/src/tools/identity-config.d.ts +13 -0
  76. package/dist/src/tools/identity-config.d.ts.map +1 -0
  77. package/dist/src/tools/identity-config.js +18 -0
  78. package/dist/src/tools/identity-fetch.d.ts +21 -0
  79. package/dist/src/tools/identity-fetch.d.ts.map +1 -0
  80. package/dist/src/tools/identity-fetch.js +63 -0
  81. package/dist/src/tools/identity-list-credentials.d.ts +15 -0
  82. package/dist/src/tools/identity-list-credentials.d.ts.map +1 -0
  83. package/dist/src/tools/identity-list-credentials.js +30 -0
  84. package/dist/src/tools/identity-list-risk-patterns.d.ts +13 -0
  85. package/dist/src/tools/identity-list-risk-patterns.d.ts.map +1 -0
  86. package/dist/src/tools/identity-list-risk-patterns.js +23 -0
  87. package/dist/src/tools/identity-list-tips.d.ts +13 -0
  88. package/dist/src/tools/identity-list-tips.d.ts.map +1 -0
  89. package/dist/src/tools/identity-list-tips.js +21 -0
  90. package/dist/src/tools/identity-login.d.ts +14 -0
  91. package/dist/src/tools/identity-login.d.ts.map +1 -0
  92. package/dist/src/tools/identity-login.js +40 -0
  93. package/dist/src/tools/identity-logout.d.ts +13 -0
  94. package/dist/src/tools/identity-logout.d.ts.map +1 -0
  95. package/dist/src/tools/identity-logout.js +24 -0
  96. package/dist/src/tools/identity-risk-check.d.ts +29 -0
  97. package/dist/src/tools/identity-risk-check.d.ts.map +1 -0
  98. package/dist/src/tools/identity-risk-check.js +54 -0
  99. package/dist/src/tools/identity-set-binding.d.ts +16 -0
  100. package/dist/src/tools/identity-set-binding.d.ts.map +1 -0
  101. package/dist/src/tools/identity-set-binding.js +31 -0
  102. package/dist/src/tools/identity-status.d.ts +13 -0
  103. package/dist/src/tools/identity-status.d.ts.map +1 -0
  104. package/dist/src/tools/identity-status.js +41 -0
  105. package/dist/src/tools/identity-unset-binding.d.ts +15 -0
  106. package/dist/src/tools/identity-unset-binding.d.ts.map +1 -0
  107. package/dist/src/tools/identity-unset-binding.js +25 -0
  108. package/dist/src/tools/identity-whoami.d.ts +13 -0
  109. package/dist/src/tools/identity-whoami.d.ts.map +1 -0
  110. package/dist/src/tools/identity-whoami.js +38 -0
  111. package/dist/src/types.d.ts +93 -0
  112. package/dist/src/types.d.ts.map +1 -0
  113. package/dist/src/types.js +5 -0
  114. package/dist/src/utils/approval-channel.d.ts +11 -0
  115. package/dist/src/utils/approval-channel.d.ts.map +1 -0
  116. package/dist/src/utils/approval-channel.js +13 -0
  117. package/dist/src/utils/auth.d.ts +24 -0
  118. package/dist/src/utils/auth.d.ts.map +1 -0
  119. package/dist/src/utils/auth.js +44 -0
  120. package/dist/src/utils/derive-session-key.d.ts +78 -0
  121. package/dist/src/utils/derive-session-key.d.ts.map +1 -0
  122. package/dist/src/utils/derive-session-key.js +198 -0
  123. package/openclaw.plugin.json +162 -0
  124. package/package.json +33 -0
  125. package/skills/SKILL.md +230 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * identity_unset_binding: remove credential env binding.
3
+ */
4
+ import type { PluginToolContext } from "../types.js";
5
+ import type { IdentityActionsDeps } from "../actions/identity-actions.js";
6
+ export declare function createIdentityUnsetBindingTool(deps: IdentityActionsDeps): (ctx: PluginToolContext) => {
7
+ name: string;
8
+ label: string;
9
+ description: string;
10
+ parameters: import("@sinclair/typebox").TObject<{
11
+ provider: import("@sinclair/typebox").TString;
12
+ }>;
13
+ execute: (_toolCallId: any, params: any) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<unknown>>;
14
+ };
15
+ //# sourceMappingURL=identity-unset-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-unset-binding.d.ts","sourceRoot":"","sources":["../../../src/tools/identity-unset-binding.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,mBAAmB,IAC9D,KAAK,iBAAiB;;;;;;;;EAiB/B"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * identity_unset_binding: remove credential env binding.
3
+ */
4
+ import { Type } from "@sinclair/typebox";
5
+ import { jsonResult } from "openclaw/plugin-sdk";
6
+ import { runUnsetBinding } from "../actions/identity-actions.js";
7
+ export function createIdentityUnsetBindingTool(deps) {
8
+ return (ctx) => ({
9
+ name: "identity_unset_binding",
10
+ label: "Identity Unset Binding",
11
+ description: "Remove credential env binding for a provider.",
12
+ parameters: Type.Object({
13
+ provider: Type.String({ description: "Provider name (e.g. google)" }),
14
+ }),
15
+ execute: async (_toolCallId, params) => {
16
+ const sessionKey = ctx.sessionKey;
17
+ if (!sessionKey) {
18
+ return jsonResult({ ok: false, error: "No session context" });
19
+ }
20
+ const p = params;
21
+ const result = await runUnsetBinding(deps, sessionKey, { provider: p.provider });
22
+ return jsonResult(result);
23
+ },
24
+ });
25
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * identity_whoami: return current session identity (sub, TIP status) for the caller's session.
3
+ */
4
+ import type { PluginToolContext } from "../types.js";
5
+ import type { IdentityActionsDeps } from "../actions/identity-actions.js";
6
+ export declare function createIdentityWhoamiTool(deps: IdentityActionsDeps): (ctx: PluginToolContext) => {
7
+ name: string;
8
+ label: string;
9
+ description: string;
10
+ parameters: import("@sinclair/typebox").TObject<{}>;
11
+ execute: () => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<unknown>>;
12
+ };
13
+ //# sourceMappingURL=identity-whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-whoami.d.ts","sourceRoot":"","sources":["../../../src/tools/identity-whoami.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,IACxD,KAAK,iBAAiB;;;;;;EA+B/B"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * identity_whoami: return current session identity (sub, TIP status) for the caller's session.
3
+ */
4
+ import { Type } from "@sinclair/typebox";
5
+ import { jsonResult } from "openclaw/plugin-sdk";
6
+ import { runStatus } from "../actions/identity-actions.js";
7
+ export function createIdentityWhoamiTool(deps) {
8
+ return (ctx) => {
9
+ const sessionKey = ctx.sessionKey;
10
+ return {
11
+ name: "identity_whoami",
12
+ label: "Identity Whoami",
13
+ description: "Show the current session's identity (user sub, TIP status).",
14
+ parameters: Type.Object({}),
15
+ execute: async () => {
16
+ if (!sessionKey) {
17
+ return jsonResult({ sub: null, hasTip: false, error: "No session context" });
18
+ }
19
+ const result = await runStatus(deps, sessionKey, ctx.config);
20
+ const now = Date.now();
21
+ return jsonResult({
22
+ sub: result.sub,
23
+ hasTip: result.hasTip,
24
+ loggedIn: result.loggedIn,
25
+ sessionKey: sessionKey.slice(0, 40) + (sessionKey.length > 40 ? "..." : ""),
26
+ sessionLoginAt: result.sessionLoginAt ?? undefined,
27
+ sessionExpiresAt: result.sessionExpiresAt ?? undefined,
28
+ tipIssuedAt: result.tipIssuedAt ?? undefined,
29
+ tipExpiresAt: result.tipExpiresAt ?? undefined,
30
+ tipExpiresInSeconds: result.tipExpiresAt != null && result.tipExpiresAt > now
31
+ ? Math.floor((result.tipExpiresAt - now) / 1000)
32
+ : undefined,
33
+ tipChain: result.tipChain,
34
+ });
35
+ },
36
+ };
37
+ };
38
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Shared types for this plugin.
3
+ * Keep this file dependency-free (types only) so it can be safely imported from entrypoints.
4
+ */
5
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
6
+ /**
7
+ * Context passed to plugin tool factories. Mirrors OpenClawPluginToolContext (not exported from SDK).
8
+ */
9
+ export type PluginToolContext = {
10
+ config?: OpenClawConfig;
11
+ workspaceDir?: string;
12
+ agentDir?: string;
13
+ agentId?: string;
14
+ sessionKey?: string;
15
+ messageChannel?: string;
16
+ agentAccountId?: string;
17
+ sandboxed?: boolean;
18
+ };
19
+ export type IdentityConfig = {
20
+ endpoint?: string;
21
+ accessKeyId?: string;
22
+ secretAccessKey?: string;
23
+ sessionToken?: string;
24
+ credentialsFile?: string;
25
+ roleTrn?: string;
26
+ workloadPoolName?: string;
27
+ workloadName?: string;
28
+ audience?: string[];
29
+ durationSeconds?: number;
30
+ };
31
+ export type UserPoolConfig = {
32
+ /** Explicit: discovery URL for OIDC. */
33
+ discoveryUrl?: string;
34
+ clientId?: string;
35
+ clientSecret?: string;
36
+ callbackUrl?: string;
37
+ scope?: string;
38
+ /** Dynamic (from_veidentity): resolve by name, no manual clientId needed. */
39
+ userPoolName?: string;
40
+ clientName?: string;
41
+ autoCreate?: boolean;
42
+ };
43
+ export type AuthzConfig = {
44
+ /** Enable AuthZ (TIP + CheckPermission + risk approval). Default: false. */
45
+ enable?: boolean;
46
+ /** Namespace for CheckPermission (Cedar policy). Default: "default". */
47
+ namespaceName?: string;
48
+ /** Skip TIP+CheckPermission for built-in low-risk tools. Default: true. */
49
+ lowRiskBypass?: boolean;
50
+ /** Extra tool names to treat as low-risk. */
51
+ lowRiskTools?: string[];
52
+ /** Require user approval for high-risk tools after CheckPermission. Default: true when enable. */
53
+ requireRiskApproval?: boolean;
54
+ /** Use LLM for risk evaluation when rules are ambiguous. Default: false. */
55
+ enableLlmRiskCheck?: boolean;
56
+ /** LLM provider config for risk check. Required when enableLlmRiskCheck is true. */
57
+ llmRiskCheck?: {
58
+ /** Base URL: Ollama (http://localhost:11434) or OpenAI-compatible (https://api.openai.com/v1) */
59
+ endpoint: string;
60
+ /** "ollama" for /api/generate, "openai-completions" for /chat/completions */
61
+ api?: "ollama" | "openai-completions";
62
+ /** Model name (e.g. qwen3:8b, gpt-4o-mini) */
63
+ model: string;
64
+ /** API key for OpenAI-compatible providers (omit for Ollama) */
65
+ apiKey?: string;
66
+ /** Timeout in ms. Default: 10000 */
67
+ timeoutMs?: number;
68
+ /** Cache TTL in ms for same tool+params. Default: 300000 (5 min). Set 0 to disable. */
69
+ cacheTtlMs?: number;
70
+ };
71
+ /** Approval TTL in seconds. Default: 300. */
72
+ approvalTtlSeconds?: number;
73
+ };
74
+ export type PluginConfig = {
75
+ /** Identity service config. Alias: cis (deprecated). */
76
+ identity?: IdentityConfig;
77
+ cis?: IdentityConfig;
78
+ userpool?: UserPoolConfig;
79
+ authz?: AuthzConfig;
80
+ };
81
+ export type PluginCommandContext = {
82
+ senderId?: string;
83
+ channel: string;
84
+ channelId?: string;
85
+ isAuthorizedSender: boolean;
86
+ args?: string;
87
+ commandBody: string;
88
+ config: OpenClawConfig;
89
+ from?: string;
90
+ to?: string;
91
+ accountId?: string;
92
+ };
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types for this plugin.
3
+ * Keep this file dependency-free (types only) so it can be safely imported from entrypoints.
4
+ */
5
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Determine if session supports sync approval (sendMessage + poll).
3
+ * Channel sessions (Feishu, Telegram, etc.) support it; webchat/TUI do not.
4
+ */
5
+ /**
6
+ * Returns true when sessionKey can be delivered to (sendMessage works).
7
+ * Those sessions use sync approval (poll until user approves).
8
+ * Returns false for webchat/TUI (agent:main:main etc) - use retry flow.
9
+ */
10
+ export declare function supportsSyncApproval(sessionKey: string | undefined | null): boolean;
11
+ //# sourceMappingURL=approval-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-channel.d.ts","sourceRoot":"","sources":["../../../src/utils/approval-channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAEnF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Determine if session supports sync approval (sendMessage + poll).
3
+ * Channel sessions (Feishu, Telegram, etc.) support it; webchat/TUI do not.
4
+ */
5
+ import { parseSessionKeyToDeliveryTarget } from "./derive-session-key.js";
6
+ /**
7
+ * Returns true when sessionKey can be delivered to (sendMessage works).
8
+ * Those sessions use sync approval (poll until user approves).
9
+ * Returns false for webchat/TUI (agent:main:main etc) - use retry flow.
10
+ */
11
+ export function supportsSyncApproval(sessionKey) {
12
+ return parseSessionKeyToDeliveryTarget(sessionKey ?? "") !== null;
13
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auth utilities (veadk-style).
3
+ * Parse TIP token for principal and delegation chain per RFC 8693.
4
+ *
5
+ * @see https://github.com/volcengine/veadk-python/blob/main/veadk/utils/auth.py
6
+ */
7
+ export type DelegationChain = {
8
+ /** End user subject from JWT `sub`. */
9
+ principalId: string;
10
+ /** Actors from nested `act` claims (outermost first, e.g. [agent1, agent2]). */
11
+ actors: string[];
12
+ };
13
+ /**
14
+ * Extract subject and delegation chain from JWT (TIP / workload token).
15
+ * Returns the primary subject (user) and the chain of actors who acted on behalf.
16
+ *
17
+ * @example
18
+ * // User → Agent1 → Agent2
19
+ * const { principalId, actors } = extractDelegationChainFromJwt(token);
20
+ * // Returns: { principalId: "user1", actors: ["agent1", "agent2"] }
21
+ * // principal = user1, originalCallers = [agent1, agent2]
22
+ */
23
+ export declare function extractDelegationChainFromJwt(token: string): DelegationChain | null;
24
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/utils/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA6BnF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Auth utilities (veadk-style).
3
+ * Parse TIP token for principal and delegation chain per RFC 8693.
4
+ *
5
+ * @see https://github.com/volcengine/veadk-python/blob/main/veadk/utils/auth.py
6
+ */
7
+ /**
8
+ * Extract subject and delegation chain from JWT (TIP / workload token).
9
+ * Returns the primary subject (user) and the chain of actors who acted on behalf.
10
+ *
11
+ * @example
12
+ * // User → Agent1 → Agent2
13
+ * const { principalId, actors } = extractDelegationChainFromJwt(token);
14
+ * // Returns: { principalId: "user1", actors: ["agent1", "agent2"] }
15
+ * // principal = user1, originalCallers = [agent1, agent2]
16
+ */
17
+ export function extractDelegationChainFromJwt(token) {
18
+ try {
19
+ const raw = token.startsWith("Bearer ") || token.startsWith("bearer ") ? token.slice(7) : token;
20
+ const parts = raw.split(".");
21
+ if (parts.length !== 3)
22
+ return null;
23
+ let payloadPart = parts[1];
24
+ const pad = payloadPart.length % 4;
25
+ if (pad)
26
+ payloadPart += "=".repeat(4 - pad);
27
+ const payload = JSON.parse(Buffer.from(payloadPart, "base64url").toString("utf-8"));
28
+ const sub = payload.sub;
29
+ if (!sub)
30
+ return null;
31
+ const actors = [];
32
+ let act = payload.act;
33
+ while (act && typeof act === "object") {
34
+ const actorSub = act.sub;
35
+ if (actorSub)
36
+ actors.push(String(actorSub));
37
+ act = act.act;
38
+ }
39
+ return { principalId: String(sub), actors };
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Derive sessionKey and agentId from command context.
3
+ * Logic aligned with OpenClaw routing buildAgentPeerSessionKey.
4
+ */
5
+ /** Minimal config shape for session/agent resolution. Compatible with OpenClawConfig. */
6
+ export type ConfigWithSession = {
7
+ session?: {
8
+ dmScope?: string;
9
+ };
10
+ agents?: {
11
+ defaults?: {
12
+ id?: string;
13
+ agentId?: string;
14
+ };
15
+ };
16
+ };
17
+ type DeriveSessionKeyParams = {
18
+ channel: string;
19
+ senderId?: string;
20
+ from?: string;
21
+ to?: string;
22
+ accountId?: string;
23
+ config: ConfigWithSession;
24
+ };
25
+ /**
26
+ * Derive agentId from config. Fallback when ctx.agentId and sessionKey are not available.
27
+ */
28
+ export declare function deriveAgentId(config: ConfigWithSession): string;
29
+ /**
30
+ * Parse agentId from sessionKey. Format: agent:{agentId}:{rest}
31
+ * Returns null if sessionKey is not in agent: form.
32
+ */
33
+ export declare function parseAgentIdFromSessionKey(sessionKey: string | undefined | null): string | null;
34
+ export type ResolveAgentIdParams = {
35
+ /** From hook ctx.agentId - preferred when available (sub-agent, workspace-bound). */
36
+ agentId?: string;
37
+ /** Parse from sessionKey when agentId not provided. */
38
+ sessionKey?: string;
39
+ /** Fallback when neither agentId nor sessionKey yields a value. */
40
+ config?: ConfigWithSession;
41
+ };
42
+ /**
43
+ * Resolve agentId with priority: ctx.agentId > parse from sessionKey > config.
44
+ * Use in hooks (prefer ctx.agentId) and commands (parse from sessionKey or config).
45
+ */
46
+ export declare function resolveAgentId(params: ResolveAgentIdParams): string;
47
+ /**
48
+ * Derive sessionKey from command context.
49
+ * Matches OpenClaw routing buildAgentPeerSessionKey for common cases.
50
+ */
51
+ export declare function deriveSessionKey(params: DeriveSessionKeyParams): string | null;
52
+ export type SessionKeyDeliveryTarget = {
53
+ channel: string;
54
+ to: string;
55
+ /** For feishu per-account sessions (agent:main:feishu:default:direct:ou_xxx). */
56
+ accountId?: string;
57
+ };
58
+ /** Command context shape (subset of PluginCommandContext). */
59
+ export type CommandContextForDelivery = {
60
+ channel: string;
61
+ from?: string;
62
+ to?: string;
63
+ accountId?: string;
64
+ };
65
+ /**
66
+ * Derive delivery target directly from command context (channel, from, to).
67
+ * Use this when sessionKey cannot be parsed reliably.
68
+ * ctx.to/from are channel-scoped (e.g. "telegram:123", "feishu:user:ou_xxx").
69
+ */
70
+ export declare function deriveDeliveryTargetFromContext(ctx: CommandContextForDelivery): SessionKeyDeliveryTarget | null;
71
+ /**
72
+ * Parse sessionKey to delivery target for sending a message back to the user's channel.
73
+ * Returns null if sessionKey cannot be parsed or channel is not sendable.
74
+ * Used after OIDC login to notify the user in their chat.
75
+ */
76
+ export declare function parseSessionKeyToDeliveryTarget(sessionKey: string | undefined | null): SessionKeyDeliveryTarget | null;
77
+ export {};
78
+ //# sourceMappingURL=derive-session-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-session-key.d.ts","sourceRoot":"","sources":["../../../src/utils/derive-session-key.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,yFAAyF;AACzF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;CAC3D,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAUF;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAM/F;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CASnE;AAyBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CA4B9E;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAaF,8DAA8D;AAC9D,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,yBAAyB,GAC7B,wBAAwB,GAAG,IAAI,CAmBjC;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GACpC,wBAAwB,GAAG,IAAI,CAyDjC"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Derive sessionKey and agentId from command context.
3
+ * Logic aligned with OpenClaw routing buildAgentPeerSessionKey.
4
+ */
5
+ const DEFAULT_AGENT_ID = "main";
6
+ const DEFAULT_ACCOUNT_ID = "default";
7
+ function normalizeAgentId(value) {
8
+ const trimmed = (value ?? "").trim();
9
+ return trimmed ? trimmed.toLowerCase() : DEFAULT_AGENT_ID;
10
+ }
11
+ /**
12
+ * Derive agentId from config. Fallback when ctx.agentId and sessionKey are not available.
13
+ */
14
+ export function deriveAgentId(config) {
15
+ return normalizeAgentId(config.agents?.defaults?.id ?? DEFAULT_AGENT_ID);
16
+ }
17
+ /**
18
+ * Parse agentId from sessionKey. Format: agent:{agentId}:{rest}
19
+ * Returns null if sessionKey is not in agent: form.
20
+ */
21
+ export function parseAgentIdFromSessionKey(sessionKey) {
22
+ const raw = (sessionKey ?? "").trim();
23
+ if (!raw || !raw.toLowerCase().startsWith("agent:"))
24
+ return null;
25
+ const parts = raw.split(":");
26
+ const agentId = parts[1]?.trim();
27
+ return agentId ? agentId : null;
28
+ }
29
+ /**
30
+ * Resolve agentId with priority: ctx.agentId > parse from sessionKey > config.
31
+ * Use in hooks (prefer ctx.agentId) and commands (parse from sessionKey or config).
32
+ */
33
+ export function resolveAgentId(params) {
34
+ const { agentId, sessionKey, config } = params;
35
+ if (agentId != null && agentId.trim()) {
36
+ return normalizeAgentId(agentId);
37
+ }
38
+ const fromSessionKey = parseAgentIdFromSessionKey(sessionKey);
39
+ if (fromSessionKey)
40
+ return normalizeAgentId(fromSessionKey);
41
+ if (config)
42
+ return deriveAgentId(config);
43
+ return DEFAULT_AGENT_ID;
44
+ }
45
+ function normalizeAccountId(value) {
46
+ const trimmed = (value ?? "").trim().toLowerCase();
47
+ return trimmed || DEFAULT_ACCOUNT_ID;
48
+ }
49
+ /**
50
+ * Extract peer/chat id from from/to for group sessions.
51
+ * Channel-specific heuristics (e.g. telegram:group:123 or telegram:123 for group chat).
52
+ */
53
+ function extractGroupPeerId(channel, from, to) {
54
+ const raw = (to ?? from ?? "").trim();
55
+ if (!raw)
56
+ return null;
57
+ const lower = raw.toLowerCase();
58
+ const channelPrefix = `${channel}:`;
59
+ if (lower.startsWith(channelPrefix)) {
60
+ const rest = raw.slice(channelPrefix.length);
61
+ const parts = rest.split(":");
62
+ if (parts[0] === "group" && parts[1])
63
+ return parts[1];
64
+ if (parts.length >= 1)
65
+ return parts[0];
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * Derive sessionKey from command context.
71
+ * Matches OpenClaw routing buildAgentPeerSessionKey for common cases.
72
+ */
73
+ export function deriveSessionKey(params) {
74
+ const { channel, senderId, from, to, accountId, config } = params;
75
+ const agentId = deriveAgentId(config);
76
+ const dmScope = config.session?.dmScope;
77
+ const ch = (channel ?? "").trim().toLowerCase() || "unknown";
78
+ const groupPeerId = extractGroupPeerId(ch, from, to);
79
+ const isGroup = Boolean(groupPeerId);
80
+ if (isGroup && groupPeerId) {
81
+ return `agent:${agentId}:${ch}:group:${groupPeerId.toLowerCase()}`;
82
+ }
83
+ const peerId = (senderId ?? "").trim().toLowerCase();
84
+ if (!peerId)
85
+ return null;
86
+ if (dmScope === "per-account-channel-peer") {
87
+ const acc = normalizeAccountId(accountId);
88
+ return `agent:${agentId}:${ch}:${acc}:direct:${peerId}`;
89
+ }
90
+ if (dmScope === "per-channel-peer") {
91
+ return `agent:${agentId}:${ch}:direct:${peerId}`;
92
+ }
93
+ if (dmScope === "per-peer") {
94
+ return `agent:${agentId}:direct:${peerId}`;
95
+ }
96
+ return `agent:${agentId}:main`;
97
+ }
98
+ const SENDABLE_CHANNELS = new Set([
99
+ "telegram",
100
+ "slack",
101
+ "discord",
102
+ "signal",
103
+ "imessage",
104
+ "whatsapp",
105
+ "line",
106
+ "feishu",
107
+ ]);
108
+ /**
109
+ * Derive delivery target directly from command context (channel, from, to).
110
+ * Use this when sessionKey cannot be parsed reliably.
111
+ * ctx.to/from are channel-scoped (e.g. "telegram:123", "feishu:user:ou_xxx").
112
+ */
113
+ export function deriveDeliveryTargetFromContext(ctx) {
114
+ const ch = (ctx.channel ?? "").trim().toLowerCase();
115
+ if (!ch || !SENDABLE_CHANNELS.has(ch))
116
+ return null;
117
+ const rawTo = (ctx.to ?? ctx.from ?? "").trim();
118
+ if (!rawTo)
119
+ return null;
120
+ const lowerTo = rawTo.toLowerCase();
121
+ let to = rawTo;
122
+ if (lowerTo.startsWith(`${ch}:`)) {
123
+ to = rawTo.slice(ch.length + 1);
124
+ }
125
+ if (ch === "feishu") {
126
+ if (!to.startsWith("user:") && !to.startsWith("chat:") && !to.startsWith("open_id:")) {
127
+ to = to.startsWith("oc_") ? `chat:${to}` : `user:${to}`;
128
+ }
129
+ }
130
+ if (ch === "slack" && /^[UW]\w+$/i.test(to)) {
131
+ to = `user:${to}`;
132
+ }
133
+ return { channel: ch, to, accountId: ctx.accountId };
134
+ }
135
+ /**
136
+ * Parse sessionKey to delivery target for sending a message back to the user's channel.
137
+ * Returns null if sessionKey cannot be parsed or channel is not sendable.
138
+ * Used after OIDC login to notify the user in their chat.
139
+ */
140
+ export function parseSessionKeyToDeliveryTarget(sessionKey) {
141
+ const raw = (sessionKey ?? "").trim();
142
+ if (!raw || !raw.toLowerCase().startsWith("agent:"))
143
+ return null;
144
+ const parts = raw.split(":");
145
+ if (parts.length < 5)
146
+ return null;
147
+ const channel = parts[2]?.toLowerCase();
148
+ if (!channel || !SENDABLE_CHANNELS.has(channel))
149
+ return null;
150
+ const scope = parts[3]?.toLowerCase();
151
+ const isDirect = scope === "direct" || scope === "dm";
152
+ if (isDirect) {
153
+ const peerId = parts[4]?.trim();
154
+ if (!peerId)
155
+ return null;
156
+ if (channel === "slack") {
157
+ return {
158
+ channel,
159
+ to: peerId.startsWith("U") || peerId.startsWith("W") ? `user:${peerId}` : peerId,
160
+ };
161
+ }
162
+ if (channel === "feishu") {
163
+ return { channel, to: `user:${peerId}` };
164
+ }
165
+ return { channel, to: `${channel}:${peerId}` };
166
+ }
167
+ if (scope === "group") {
168
+ const groupId = parts[4]?.trim();
169
+ if (!groupId)
170
+ return null;
171
+ if (channel === "feishu") {
172
+ return { channel, to: `chat:${groupId}` };
173
+ }
174
+ if (parts[5]?.toLowerCase() === "topic" && parts[6]) {
175
+ return { channel, to: `${channel}:group:${groupId}:topic:${parts[6]}` };
176
+ }
177
+ return { channel, to: `${channel}:group:${groupId}` };
178
+ }
179
+ // per-account-channel-peer: agent:main:feishu:default:direct:ou_xxx
180
+ if (scope && !isDirect && scope !== "group" && parts[4]?.toLowerCase() === "direct") {
181
+ const peerId = parts[5]?.trim();
182
+ if (!peerId)
183
+ return null;
184
+ const accountId = scope;
185
+ if (channel === "slack") {
186
+ return {
187
+ channel,
188
+ to: peerId.startsWith("U") || peerId.startsWith("W") ? `user:${peerId}` : peerId,
189
+ accountId,
190
+ };
191
+ }
192
+ if (channel === "feishu") {
193
+ return { channel, to: `user:${peerId}`, accountId };
194
+ }
195
+ return { channel, to: `${channel}:${peerId}`, accountId };
196
+ }
197
+ return null;
198
+ }