ofiere-openclaw-plugin 4.56.9 → 4.56.10

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/index.ts CHANGED
@@ -1,105 +1,105 @@
1
- // index.ts — Ofiere PM Plugin for OpenClaw
2
- // Matches Composio plugin pattern: plain object export + api.on()
3
-
4
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
5
- import { parseOfiereConfig } from "./src/config.js";
6
- import { getSupabase } from "./src/supabase.js";
7
- import { registerTools, probeApiForAgentName } from "./src/tools.js";
8
- import { getSystemPrompt } from "./src/prompt.js";
9
- import { registerCli } from "./src/cli.js";
10
- import { seedAgentCache } from "./src/agent-resolver.js";
11
-
12
- const ofierePlugin = {
13
- id: "ofiere",
14
- name: "Ofiere PM",
15
- description:
16
- "Manage Ofiere PM tasks, agents, and projects directly from the agent. " +
17
- "Create tasks, update progress, assign agents — all synced to the dashboard in real time.",
18
-
19
- register(api: OpenClawPluginApi) {
20
- const config = parseOfiereConfig(api.pluginConfig);
21
-
22
- // Always register CLI (even if disabled — so user can run `openclaw ofiere setup`)
23
- registerCli(api);
24
-
25
- if (!config.enabled) {
26
- api.logger.debug?.("[ofiere] Plugin disabled via config");
27
- return;
28
- }
29
-
30
- if (!config.supabaseUrl || !config.serviceRoleKey) {
31
- api.logger.warn(
32
- "[ofiere] Not configured. Run: openclaw ofiere setup",
33
- );
34
- return;
35
- }
36
-
37
- if (!config.userId) {
38
- api.logger.warn(
39
- "[ofiere] Missing userId. Run: openclaw ofiere setup",
40
- );
41
- return;
42
- }
43
-
44
- // ── Pre-seed agent cache if OFIERE_AGENT_ID is set (legacy mode) ──────
45
- if (config.agentId) {
46
- const callerName =
47
- (api as any)?.agentContext?.accountId ||
48
- (api as any)?.agentContext?.name ||
49
- (api as any)?.currentAgent?.accountId ||
50
- "";
51
- if (callerName) {
52
- seedAgentCache(callerName, config.userId, config.agentId);
53
- }
54
- }
55
-
56
- // ── State for system prompt injection ──────────────────────────────────
57
- const promptState = {
58
- toolCount: 0,
59
- agentId: config.agentId,
60
- connectError: "",
61
- ready: false,
62
- };
63
-
64
- // ── System prompt is built ONCE (it's static after init) ──────────────
65
- // No hook needed here — the brain context hook in tools.ts uses
66
- // prependSystemContext via getSystemPromptCached() to combine both
67
- // in a single hook invocation, eliminating one serial hook call.
68
- let cachedSystemPrompt = "";
69
- const getSystemPromptCached = () => {
70
- if (!cachedSystemPrompt) {
71
- cachedSystemPrompt = getSystemPrompt(promptState);
72
- }
73
- return cachedSystemPrompt;
74
- };
75
-
76
- // Hook: inject BOTH system prompt + brain context in one call
77
- api.on("before_prompt_build", () => ({
78
- prependSystemContext: getSystemPromptCached(),
79
- }));
80
-
81
- // ── Connect to Supabase and register tools ────────────────────────────
82
- try {
83
- const supabase = getSupabase(config.supabaseUrl, config.serviceRoleKey);
84
-
85
- // Probe the api object for any agent identity info (for debugging + fallback)
86
- probeApiForAgentName(api, api.logger);
87
-
88
- // registerTools now returns the count — no more hardcoding
89
- const toolCount = registerTools(api, supabase, config);
90
- promptState.toolCount = toolCount;
91
- promptState.ready = true;
92
- const agentLabel = config.agentId || "auto-detect";
93
- api.logger.info(
94
- `[ofiere] Ready — ${toolCount} meta-tools registered (agent: ${agentLabel})`,
95
- );
96
- } catch (e) {
97
- const msg = e instanceof Error ? e.message : String(e);
98
- promptState.connectError = msg;
99
- promptState.ready = true;
100
- api.logger.error(`[ofiere] Failed to initialize: ${msg}`);
101
- }
102
- },
103
- };
104
-
105
- export default ofierePlugin;
1
+ // index.ts — Ofiere PM Plugin for OpenClaw
2
+ // Matches Composio plugin pattern: plain object export + api.on()
3
+
4
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
5
+ import { parseOfiereConfig } from "./src/config.js";
6
+ import { getSupabase } from "./src/supabase.js";
7
+ import { registerTools, probeApiForAgentName } from "./src/tools.js";
8
+ import { getSystemPrompt } from "./src/prompt.js";
9
+ import { registerCli } from "./src/cli.js";
10
+ import { seedAgentCache } from "./src/agent-resolver.js";
11
+
12
+ const ofierePlugin = {
13
+ id: "ofiere",
14
+ name: "Ofiere PM",
15
+ description:
16
+ "Manage Ofiere PM tasks, agents, and projects directly from the agent. " +
17
+ "Create tasks, update progress, assign agents — all synced to the dashboard in real time.",
18
+
19
+ register(api: OpenClawPluginApi) {
20
+ const config = parseOfiereConfig(api.pluginConfig);
21
+
22
+ // Always register CLI (even if disabled — so user can run `openclaw ofiere setup`)
23
+ registerCli(api);
24
+
25
+ if (!config.enabled) {
26
+ api.logger.debug?.("[ofiere] Plugin disabled via config");
27
+ return;
28
+ }
29
+
30
+ if (!config.supabaseUrl || !config.serviceRoleKey) {
31
+ api.logger.warn(
32
+ "[ofiere] Not configured. Run: openclaw ofiere setup",
33
+ );
34
+ return;
35
+ }
36
+
37
+ if (!config.userId) {
38
+ api.logger.warn(
39
+ "[ofiere] Missing userId. Run: openclaw ofiere setup",
40
+ );
41
+ return;
42
+ }
43
+
44
+ // ── Pre-seed agent cache if OFIERE_AGENT_ID is set (legacy mode) ──────
45
+ if (config.agentId) {
46
+ const callerName =
47
+ (api as any)?.agentContext?.accountId ||
48
+ (api as any)?.agentContext?.name ||
49
+ (api as any)?.currentAgent?.accountId ||
50
+ "";
51
+ if (callerName) {
52
+ seedAgentCache(callerName, config.userId, config.agentId);
53
+ }
54
+ }
55
+
56
+ // ── State for system prompt injection ──────────────────────────────────
57
+ const promptState = {
58
+ toolCount: 0,
59
+ agentId: config.agentId,
60
+ connectError: "",
61
+ ready: false,
62
+ };
63
+
64
+ // ── System prompt is built ONCE (it's static after init) ──────────────
65
+ // No hook needed here — the brain context hook in tools.ts uses
66
+ // prependSystemContext via getSystemPromptCached() to combine both
67
+ // in a single hook invocation, eliminating one serial hook call.
68
+ let cachedSystemPrompt = "";
69
+ const getSystemPromptCached = () => {
70
+ if (!cachedSystemPrompt) {
71
+ cachedSystemPrompt = getSystemPrompt(promptState);
72
+ }
73
+ return cachedSystemPrompt;
74
+ };
75
+
76
+ // Hook: inject BOTH system prompt + brain context in one call
77
+ api.on("before_prompt_build", () => ({
78
+ prependSystemContext: getSystemPromptCached(),
79
+ }));
80
+
81
+ // ── Connect to Supabase and register tools ────────────────────────────
82
+ try {
83
+ const supabase = getSupabase(config.supabaseUrl, config.serviceRoleKey);
84
+
85
+ // Probe the api object for any agent identity info (for debugging + fallback)
86
+ probeApiForAgentName(api, api.logger);
87
+
88
+ // registerTools now returns the count — no more hardcoding
89
+ const toolCount = registerTools(api, supabase, config);
90
+ promptState.toolCount = toolCount;
91
+ promptState.ready = true;
92
+ const agentLabel = config.agentId || "auto-detect";
93
+ api.logger.info(
94
+ `[ofiere] Ready — ${toolCount} meta-tools registered (agent: ${agentLabel})`,
95
+ );
96
+ } catch (e) {
97
+ const msg = e instanceof Error ? e.message : String(e);
98
+ promptState.connectError = msg;
99
+ promptState.ready = true;
100
+ api.logger.error(`[ofiere] Failed to initialize: ${msg}`);
101
+ }
102
+ },
103
+ };
104
+
105
+ export default ofierePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "4.56.9",
3
+ "version": "4.56.10",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin for Ofiere PM - 18 meta-tools covering tasks, agents, projects, scheduling, knowledge, workflows, notifications, memory, prompts, constellation, space file management, execution plan builder, SOP management, agent brain, talent management, corporate frameworks, agent office canvas, and PM gate approvals",
6
6
  "keywords": [
@@ -1,90 +1,90 @@
1
- // src/agent-resolver.ts — Dynamic agent identity resolution
2
- // Resolves an OpenClaw account name (e.g. "ivy") to a Ofiere agent UUID.
3
- // Caches lookups so only the first call per agent hits Supabase.
4
- // Auto-registers unknown agents so multi-agent setups work out of the box.
5
-
6
- import type { SupabaseClient } from "@supabase/supabase-js";
7
-
8
- const cache = new Map<string, string>();
9
-
10
- /**
11
- * Resolves an OpenClaw accountId to a Ofiere agent UUID.
12
- *
13
- * Strategy:
14
- * 1. Check in-memory cache
15
- * 2. Look up by name (case-insensitive) in agents table
16
- * 3. If not found, auto-register a new agent record
17
- * 4. Cache the result for subsequent calls
18
- *
19
- * @param accountId - The OpenClaw account name (e.g. "ivy", "daisy")
20
- * @param userId - The Ofiere user UUID who owns this agent
21
- * @param supabase - Supabase client
22
- * @returns The Ofiere agent UUID
23
- */
24
- export async function resolveAgentId(
25
- accountId: string,
26
- userId: string,
27
- supabase: SupabaseClient,
28
- ): Promise<string> {
29
- if (!accountId) return "";
30
-
31
- const cacheKey = `${userId}:${accountId}`;
32
-
33
- // 1. Cache hit
34
- if (cache.has(cacheKey)) {
35
- return cache.get(cacheKey)!;
36
- }
37
-
38
- // 2. Look up by name OR codename in a single query (v4.30.0 optimization)
39
- const { data: existing } = await supabase
40
- .from("agents")
41
- .select("id")
42
- .eq("user_id", userId)
43
- .or(`name.ilike.${accountId},codename.ilike.${accountId}`)
44
- .limit(1)
45
- .single();
46
-
47
- if (existing?.id) {
48
- cache.set(cacheKey, existing.id);
49
- return existing.id;
50
- }
51
-
52
- // 3. Auto-register a new agent
53
- const newId = `agent-${accountId.toLowerCase()}-${Date.now()}`;
54
- const { data: created } = await supabase
55
- .from("agents")
56
- .insert({
57
- id: newId,
58
- user_id: userId,
59
- name: accountId.charAt(0).toUpperCase() + accountId.slice(1).toLowerCase(),
60
- codename: accountId.toLowerCase(),
61
- status: "active",
62
- role: "operative",
63
- level: 1,
64
- xp: 0,
65
- created_at: new Date().toISOString(),
66
- })
67
- .select("id")
68
- .single();
69
-
70
- const resolvedId = created?.id || newId;
71
- cache.set(cacheKey, resolvedId);
72
- return resolvedId;
73
- }
74
-
75
- /**
76
- * Pre-warm the cache with a known mapping.
77
- * Used when OFIERE_AGENT_ID env var is set (legacy single-agent mode).
78
- */
79
- export function seedAgentCache(accountId: string, userId: string, agentId: string): void {
80
- if (accountId && agentId) {
81
- cache.set(`${userId}:${accountId}`, agentId);
82
- }
83
- }
84
-
85
- /**
86
- * Clear the cache (useful for testing).
87
- */
88
- export function clearAgentCache(): void {
89
- cache.clear();
90
- }
1
+ // src/agent-resolver.ts — Dynamic agent identity resolution
2
+ // Resolves an OpenClaw account name (e.g. "ivy") to a Ofiere agent UUID.
3
+ // Caches lookups so only the first call per agent hits Supabase.
4
+ // Auto-registers unknown agents so multi-agent setups work out of the box.
5
+
6
+ import type { SupabaseClient } from "@supabase/supabase-js";
7
+
8
+ const cache = new Map<string, string>();
9
+
10
+ /**
11
+ * Resolves an OpenClaw accountId to a Ofiere agent UUID.
12
+ *
13
+ * Strategy:
14
+ * 1. Check in-memory cache
15
+ * 2. Look up by name (case-insensitive) in agents table
16
+ * 3. If not found, auto-register a new agent record
17
+ * 4. Cache the result for subsequent calls
18
+ *
19
+ * @param accountId - The OpenClaw account name (e.g. "ivy", "daisy")
20
+ * @param userId - The Ofiere user UUID who owns this agent
21
+ * @param supabase - Supabase client
22
+ * @returns The Ofiere agent UUID
23
+ */
24
+ export async function resolveAgentId(
25
+ accountId: string,
26
+ userId: string,
27
+ supabase: SupabaseClient,
28
+ ): Promise<string> {
29
+ if (!accountId) return "";
30
+
31
+ const cacheKey = `${userId}:${accountId}`;
32
+
33
+ // 1. Cache hit
34
+ if (cache.has(cacheKey)) {
35
+ return cache.get(cacheKey)!;
36
+ }
37
+
38
+ // 2. Look up by name OR codename in a single query (v4.30.0 optimization)
39
+ const { data: existing } = await supabase
40
+ .from("agents")
41
+ .select("id")
42
+ .eq("user_id", userId)
43
+ .or(`name.ilike.${accountId},codename.ilike.${accountId}`)
44
+ .limit(1)
45
+ .single();
46
+
47
+ if (existing?.id) {
48
+ cache.set(cacheKey, existing.id);
49
+ return existing.id;
50
+ }
51
+
52
+ // 3. Auto-register a new agent
53
+ const newId = `agent-${accountId.toLowerCase()}-${Date.now()}`;
54
+ const { data: created } = await supabase
55
+ .from("agents")
56
+ .insert({
57
+ id: newId,
58
+ user_id: userId,
59
+ name: accountId.charAt(0).toUpperCase() + accountId.slice(1).toLowerCase(),
60
+ codename: accountId.toLowerCase(),
61
+ status: "active",
62
+ role: "operative",
63
+ level: 1,
64
+ xp: 0,
65
+ created_at: new Date().toISOString(),
66
+ })
67
+ .select("id")
68
+ .single();
69
+
70
+ const resolvedId = created?.id || newId;
71
+ cache.set(cacheKey, resolvedId);
72
+ return resolvedId;
73
+ }
74
+
75
+ /**
76
+ * Pre-warm the cache with a known mapping.
77
+ * Used when OFIERE_AGENT_ID env var is set (legacy single-agent mode).
78
+ */
79
+ export function seedAgentCache(accountId: string, userId: string, agentId: string): void {
80
+ if (accountId && agentId) {
81
+ cache.set(`${userId}:${accountId}`, agentId);
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Clear the cache (useful for testing).
87
+ */
88
+ export function clearAgentCache(): void {
89
+ cache.clear();
90
+ }