ofiere-openclaw-plugin 4.50.1 → 4.52.0

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.
@@ -16,7 +16,7 @@ function ok(data) {
16
16
  function err(message) {
17
17
  return { content: [{ type: "text", text: `Error: ${message}` }] };
18
18
  }
19
- const VALID_TARGETS = ["conversation", "task", "scheduler_event"];
19
+ const VALID_TARGETS = ["conversation", "task", "scheduler_event", "subagent"];
20
20
  function isValidTargetKind(v) {
21
21
  return typeof v === "string" && VALID_TARGETS.includes(v);
22
22
  }
@@ -77,10 +77,50 @@ async function applyAttachmentWrite(args) {
77
77
  return { ok: false, error: writeErr.message };
78
78
  return { ok: true };
79
79
  }
80
+ // Cycle 11 — subagent target_kind. Writes profile-level defaults that apply
81
+ // across EVERY dispatch to the staff (unioned with per-task ids at dispatch
82
+ // time in task-dispatcher edge fn via loadStaffDefaultAttachments).
83
+ if (targetKind === "subagent") {
84
+ const col = docKind === "sop" ? "attached_sop_ids" : "attached_framework_ids";
85
+ const { data: cur, error: readErr } = await supabase
86
+ .from("agent_subagents")
87
+ .select(col)
88
+ .eq("user_id", userId)
89
+ .eq("id", targetId)
90
+ .maybeSingle();
91
+ if (readErr)
92
+ return { ok: false, error: readErr.message };
93
+ const existing = (cur?.[col]) || [];
94
+ const merged = Array.from(new Set([...existing, ...docIds]));
95
+ const { error: writeErr } = await supabase
96
+ .from("agent_subagents")
97
+ .update({ [col]: merged })
98
+ .eq("user_id", userId)
99
+ .eq("id", targetId);
100
+ if (writeErr)
101
+ return { ok: false, error: writeErr.message };
102
+ return { ok: true };
103
+ }
80
104
  return { ok: false, error: "unsupported target_kind" };
81
105
  }
82
106
  async function loadTargetIdentity(args) {
83
107
  const { supabase, userId, targetKind, targetId } = args;
108
+ // Cycle 11 — subagent target: identity is { agentId: chief_agent_id, subagentId: row.id }.
109
+ // resolveTargetTier sees subagentId set → returns "staff" tier without a chief lookup.
110
+ if (targetKind === "subagent") {
111
+ const { data } = await supabase
112
+ .from("agent_subagents")
113
+ .select("id, chief_agent_id")
114
+ .eq("user_id", userId)
115
+ .eq("id", targetId)
116
+ .maybeSingle();
117
+ if (!data)
118
+ return null;
119
+ return {
120
+ agentId: data.chief_agent_id ?? null,
121
+ subagentId: data.id ?? null,
122
+ };
123
+ }
84
124
  const tbl = targetKind === "conversation" ? "conversations" :
85
125
  targetKind === "task" ? "tasks" : "scheduler_events";
86
126
  const { data } = await supabase
package/dist/src/tools.js CHANGED
@@ -665,7 +665,16 @@ async function handleCreateTask(supabase, userId, resolveAgent, params, fallback
665
665
  // INSERTed the raw input then reassigned insertData.start_date afterward,
666
666
  // which left the DB row with the unconverted value and the response with
667
667
  // the converted one — confusing and unsafe for the scheduler.
668
- const rawStartDate = params.start_date || null;
668
+ //
669
+ // Cycle 12 fix: when delegating to a staff (subagent_id present) without
670
+ // an explicit start_date, default to now + 5s so the scheduler_event auto-
671
+ // create branch below kicks in. Without this, the task sat PENDING forever
672
+ // because processDirectTasks' date-string filter also skips it (separate
673
+ // bug, fixed in task-dispatcher v21). The 5s buffer ensures the safety
674
+ // net at line ~805 doesn't trip and shift the run to +60s.
675
+ const explicitStartDate = params.start_date || null;
676
+ const rawStartDate = explicitStartDate
677
+ ?? (params.subagent_id ? new Date(Date.now() + 5_000).toISOString() : null);
669
678
  const normalized = rawStartDate
670
679
  ? normalizeStartDate(rawStartDate, params.scheduled_time, TZ_OFFSET_HOURS)
671
680
  : null;
@@ -4943,9 +4952,9 @@ function registerSOPOps(api, supabase, userId, resolveAgent) {
4943
4952
  `- "delete": Remove SOP. Required: sop_id\n` +
4944
4953
  `- "list_subagents": List subagents for a chief. Required: chief_agent_id. (Provided here for convenience when scoping SOP authoring; team management lives in OFIERE_AGENT_OPS.)\n` +
4945
4954
  `- "apply_template": Create SOP from template. Required: agent_id, template_id. Optional: title, department\n` +
4946
- `- "propose_attach": Propose attaching SOPs to a run target (conversation/task/scheduler_event). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit.\n` +
4955
+ `- "propose_attach": Propose attaching SOPs to a target (conversation/task/scheduler_event/subagent). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit. Use target_kind="subagent" to attach SOPs to the staff PROFILE itself (applies to every dispatch); use task/conversation/scheduler_event for one-off run-scoped attach.\n` +
4947
4956
  `- "commit_attach": Commit a proposed attachment. Required: target_kind, target_id, doc_ids[], confirmation_token (from propose_attach). Only call AFTER user approves the token cost.\n` +
4948
- `Tier rule: SOPs only attach to targets whose assigned agent is Staff. Use OFIERE_FRAMEWORK_OPS for c-suite targets.\n\n` +
4957
+ `Tier rule: SOPs only attach to targets whose assigned agent is Staff (or to a subagent profile directly). Use OFIERE_FRAMEWORK_OPS for c-suite targets.\n\n` +
4949
4958
  `sop_data structure (JSON object):\n` +
4950
4959
  `{\n` +
4951
4960
  ` title: string,\n` +
@@ -4970,8 +4979,8 @@ function registerSOPOps(api, supabase, userId, resolveAgent) {
4970
4979
  agent_id: { type: "string", description: "Agent ID (required for create, list filter, apply_template)" },
4971
4980
  chief_agent_id: { type: "string", description: "Chief agent ID (required for list_subagents)" },
4972
4981
  template_id: { type: "string", description: "Template ID (required for apply_template)" },
4973
- target_kind: { type: "string", enum: ["conversation", "task", "scheduler_event"], description: "Run target kind (for propose_attach/commit_attach)" },
4974
- target_id: { type: "string", description: "Run target id (for propose_attach/commit_attach)" },
4982
+ target_kind: { type: "string", enum: ["conversation", "task", "scheduler_event", "subagent"], description: "Target kind (for propose_attach/commit_attach). 'subagent' writes to staff PROFILE (persists across all dispatches); others are run-scoped." },
4983
+ target_id: { type: "string", description: "Target id (for propose_attach/commit_attach). For target_kind='subagent', this is the agent_subagents row id." },
4975
4984
  doc_ids: { type: "array", items: { type: "string" }, description: "SOP ids to attach (for propose_attach/commit_attach)" },
4976
4985
  confirmation_token: { type: "string", description: "Token returned by propose_attach. Required for commit_attach." },
4977
4986
  title: { type: "string", description: "SOP title" },
@@ -5498,7 +5507,7 @@ function registerFrameworkOps(api, supabase, userId, resolveAgent) {
5498
5507
  `- "get": Get full framework details. Required: framework_id\n` +
5499
5508
  `- "update": Modify framework. Required: framework_id. Optional: title, content, status, department, category\n` +
5500
5509
  `- "delete": Remove framework. Required: framework_id\n` +
5501
- `- "propose_attach": Propose attaching Frameworks to a run target. Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit.\n` +
5510
+ `- "propose_attach": Propose attaching Frameworks to a target (conversation/task/scheduler_event). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit. Frameworks are c-suite only — they cannot be attached to staff subagents.\n` +
5502
5511
  `- "commit_attach": Commit a proposed attachment. Required: target_kind, target_id, doc_ids[], confirmation_token (from propose_attach). Only call AFTER user approves the token cost.\n` +
5503
5512
  `Tier rule: Frameworks only attach to targets whose assigned agent is C-Suite. Use OFIERE_SOP_OPS for staff targets.\n\n` +
5504
5513
  `content: A JSON string containing the full framework body. Example:\n` +
@@ -1,80 +1,80 @@
1
- {
2
- "id": "ofiere",
3
- "name": "Ofiere PM",
4
- "description": "Manage Ofiere PM tasks, agents, and projects directly from the agent. The agent can create tasks, update progress, list work items, and more — all synced to the Ofiere dashboard in real time.",
5
- "configSchema": {
6
- "type": "object",
7
- "additionalProperties": false,
8
- "properties": {
9
- "enabled": {
10
- "type": "boolean",
11
- "description": "Enable or disable the Ofiere PM integration"
12
- },
13
- "supabaseUrl": {
14
- "type": "string",
15
- "description": "Your Supabase project URL (e.g. https://xxx.supabase.co)"
16
- },
17
- "serviceRoleKey": {
18
- "type": "string",
19
- "description": "Supabase service role key for full database access"
20
- },
21
- "userId": {
22
- "type": "string",
23
- "description": "Your Ofiere user ID (UUID from auth.users)"
24
- },
25
- "agentId": {
26
- "type": "string",
27
- "description": "This agent's ID in Ofiere (e.g. 'sasha', 'ivy', 'thalia')"
28
- }
29
- }
30
- },
31
- "hooks": {
32
- "allowConversationAccess": true
33
- },
34
- "contracts": {
35
- "tools": [
36
- "OFIERE_TASK_OPS",
37
- "OFIERE_AGENT_OPS",
38
- "OFIERE_PROJECT_OPS",
39
- "OFIERE_SCHEDULE_OPS",
40
- "OFIERE_KNOWLEDGE_OPS",
41
- "OFIERE_WORKFLOW_OPS",
42
- "OFIERE_NOTIFY_OPS",
43
- "OFIERE_MEMORY_OPS",
44
- "OFIERE_PROMPT_OPS",
45
- "OFIERE_CONSTELLATION_OPS",
46
- "OFIERE_FILE_OPS",
47
- "OFIERE_PLAN_OPS",
48
- "OFIERE_SOP_OPS",
49
- "OFIERE_FRAMEWORK_OPS",
50
- "OFIERE_BRAIN_OPS",
51
- "OFIERE_TALENT_OPS"
52
- ]
53
- },
54
- "activation": {
55
- "onStartup": true
56
- },
57
- "uiHints": {
58
- "enabled": {
59
- "label": "Enable Ofiere PM",
60
- "help": "Enable or disable the Ofiere PM integration"
61
- },
62
- "supabaseUrl": {
63
- "label": "Supabase URL",
64
- "help": "Your Supabase project URL"
65
- },
66
- "serviceRoleKey": {
67
- "label": "Service Role Key",
68
- "help": "Supabase service role key (keep secret!)",
69
- "sensitive": true
70
- },
71
- "userId": {
72
- "label": "User ID",
73
- "help": "Your user UUID from the Ofiere dashboard"
74
- },
75
- "agentId": {
76
- "label": "Agent ID",
77
- "help": "This agent's ID (e.g. 'sasha')"
78
- }
79
- }
80
- }
1
+ {
2
+ "id": "ofiere",
3
+ "name": "Ofiere PM",
4
+ "description": "Manage Ofiere PM tasks, agents, and projects directly from the agent. The agent can create tasks, update progress, list work items, and more — all synced to the Ofiere dashboard in real time.",
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "enabled": {
10
+ "type": "boolean",
11
+ "description": "Enable or disable the Ofiere PM integration"
12
+ },
13
+ "supabaseUrl": {
14
+ "type": "string",
15
+ "description": "Your Supabase project URL (e.g. https://xxx.supabase.co)"
16
+ },
17
+ "serviceRoleKey": {
18
+ "type": "string",
19
+ "description": "Supabase service role key for full database access"
20
+ },
21
+ "userId": {
22
+ "type": "string",
23
+ "description": "Your Ofiere user ID (UUID from auth.users)"
24
+ },
25
+ "agentId": {
26
+ "type": "string",
27
+ "description": "This agent's ID in Ofiere (e.g. 'sasha', 'ivy', 'thalia')"
28
+ }
29
+ }
30
+ },
31
+ "hooks": {
32
+ "allowConversationAccess": true
33
+ },
34
+ "contracts": {
35
+ "tools": [
36
+ "OFIERE_TASK_OPS",
37
+ "OFIERE_AGENT_OPS",
38
+ "OFIERE_PROJECT_OPS",
39
+ "OFIERE_SCHEDULE_OPS",
40
+ "OFIERE_KNOWLEDGE_OPS",
41
+ "OFIERE_WORKFLOW_OPS",
42
+ "OFIERE_NOTIFY_OPS",
43
+ "OFIERE_MEMORY_OPS",
44
+ "OFIERE_PROMPT_OPS",
45
+ "OFIERE_CONSTELLATION_OPS",
46
+ "OFIERE_FILE_OPS",
47
+ "OFIERE_PLAN_OPS",
48
+ "OFIERE_SOP_OPS",
49
+ "OFIERE_FRAMEWORK_OPS",
50
+ "OFIERE_BRAIN_OPS",
51
+ "OFIERE_TALENT_OPS"
52
+ ]
53
+ },
54
+ "activation": {
55
+ "onStartup": true
56
+ },
57
+ "uiHints": {
58
+ "enabled": {
59
+ "label": "Enable Ofiere PM",
60
+ "help": "Enable or disable the Ofiere PM integration"
61
+ },
62
+ "supabaseUrl": {
63
+ "label": "Supabase URL",
64
+ "help": "Your Supabase project URL"
65
+ },
66
+ "serviceRoleKey": {
67
+ "label": "Service Role Key",
68
+ "help": "Supabase service role key (keep secret!)",
69
+ "sensitive": true
70
+ },
71
+ "userId": {
72
+ "label": "User ID",
73
+ "help": "Your user UUID from the Ofiere dashboard"
74
+ },
75
+ "agentId": {
76
+ "label": "Agent ID",
77
+ "help": "This agent's ID (e.g. 'sasha')"
78
+ }
79
+ }
80
+ }
package/package.json CHANGED
@@ -1,50 +1,50 @@
1
- {
2
- "name": "ofiere-openclaw-plugin",
3
- "version": "4.50.1",
4
- "type": "module",
5
- "description": "OpenClaw plugin for Ofiere PM - 16 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, and corporate frameworks",
6
- "keywords": ["openclaw", "ofiere", "project-management", "agents", "plugin"],
7
- "homepage": "https://github.com/gilanggemar/Ofiere",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/gilanggemar/Ofiere.git"
11
- },
12
- "license": "MIT",
13
- "main": "./dist/index.js",
14
- "files": [
15
- "index.ts",
16
- "src",
17
- "dist",
18
- "openclaw.plugin.json",
19
- "README.md",
20
- "tsconfig.json"
21
- ],
22
- "scripts": {
23
- "typecheck": "tsc --noEmit",
24
- "build": "tsc",
25
- "prepublishOnly": "npm run build"
26
- },
27
- "openclaw": {
28
- "extensions": [
29
- "./index.ts"
30
- ],
31
- "runtimeExtensions": [
32
- "./dist/index.js"
33
- ],
34
- "compat": {
35
- "pluginApi": ">=2026.3.24-beta.2",
36
- "minGatewayVersion": "2026.3.24-beta.2"
37
- },
38
- "build": {
39
- "openclawVersion": "2026.3.24-beta.2",
40
- "pluginSdkVersion": "2026.3.24-beta.2"
41
- }
42
- },
43
- "dependencies": {
44
- "@supabase/supabase-js": "^2.98.0",
45
- "zod": "^3.25.11"
46
- },
47
- "devDependencies": {
48
- "typescript": "^5.6.0"
49
- }
50
- }
1
+ {
2
+ "name": "ofiere-openclaw-plugin",
3
+ "version": "4.52.0",
4
+ "type": "module",
5
+ "description": "OpenClaw plugin for Ofiere PM - 16 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, and corporate frameworks",
6
+ "keywords": ["openclaw", "ofiere", "project-management", "agents", "plugin"],
7
+ "homepage": "https://github.com/gilanggemar/Ofiere",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/gilanggemar/Ofiere.git"
11
+ },
12
+ "license": "MIT",
13
+ "main": "./dist/index.js",
14
+ "files": [
15
+ "index.ts",
16
+ "src",
17
+ "dist",
18
+ "openclaw.plugin.json",
19
+ "README.md",
20
+ "tsconfig.json"
21
+ ],
22
+ "scripts": {
23
+ "typecheck": "tsc --noEmit",
24
+ "build": "tsc",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "openclaw": {
28
+ "extensions": [
29
+ "./index.ts"
30
+ ],
31
+ "runtimeExtensions": [
32
+ "./dist/index.js"
33
+ ],
34
+ "compat": {
35
+ "pluginApi": ">=2026.3.24-beta.2",
36
+ "minGatewayVersion": "2026.3.24-beta.2"
37
+ },
38
+ "build": {
39
+ "openclawVersion": "2026.3.24-beta.2",
40
+ "pluginSdkVersion": "2026.3.24-beta.2"
41
+ }
42
+ },
43
+ "dependencies": {
44
+ "@supabase/supabase-js": "^2.98.0",
45
+ "zod": "^3.25.11"
46
+ },
47
+ "devDependencies": {
48
+ "typescript": "^5.6.0"
49
+ }
50
+ }
@@ -27,10 +27,10 @@ function err(message: string): ToolResult {
27
27
  return { content: [{ type: "text" as const, text: `Error: ${message}` }] };
28
28
  }
29
29
 
30
- export type TargetKind = "conversation" | "task" | "scheduler_event";
30
+ export type TargetKind = "conversation" | "task" | "scheduler_event" | "subagent";
31
31
  export type DocKind = "sop" | "framework";
32
32
 
33
- const VALID_TARGETS: ReadonlyArray<TargetKind> = ["conversation", "task", "scheduler_event"];
33
+ const VALID_TARGETS: ReadonlyArray<TargetKind> = ["conversation", "task", "scheduler_event", "subagent"];
34
34
  function isValidTargetKind(v: unknown): v is TargetKind {
35
35
  return typeof v === "string" && (VALID_TARGETS as readonly string[]).includes(v);
36
36
  }
@@ -97,6 +97,29 @@ async function applyAttachmentWrite(args: {
97
97
  return { ok: true };
98
98
  }
99
99
 
100
+ // Cycle 11 — subagent target_kind. Writes profile-level defaults that apply
101
+ // across EVERY dispatch to the staff (unioned with per-task ids at dispatch
102
+ // time in task-dispatcher edge fn via loadStaffDefaultAttachments).
103
+ if (targetKind === "subagent") {
104
+ const col = docKind === "sop" ? "attached_sop_ids" : "attached_framework_ids";
105
+ const { data: cur, error: readErr } = await supabase
106
+ .from("agent_subagents")
107
+ .select(col)
108
+ .eq("user_id", userId)
109
+ .eq("id", targetId)
110
+ .maybeSingle();
111
+ if (readErr) return { ok: false, error: readErr.message };
112
+ const existing = ((cur as Record<string, string[] | undefined> | null)?.[col]) || [];
113
+ const merged = Array.from(new Set([...existing, ...docIds]));
114
+ const { error: writeErr } = await supabase
115
+ .from("agent_subagents")
116
+ .update({ [col]: merged })
117
+ .eq("user_id", userId)
118
+ .eq("id", targetId);
119
+ if (writeErr) return { ok: false, error: writeErr.message };
120
+ return { ok: true };
121
+ }
122
+
100
123
  return { ok: false, error: "unsupported target_kind" };
101
124
  }
102
125
 
@@ -113,6 +136,21 @@ async function loadTargetIdentity(args: {
113
136
  targetId: string;
114
137
  }): Promise<TargetIdentity | null> {
115
138
  const { supabase, userId, targetKind, targetId } = args;
139
+ // Cycle 11 — subagent target: identity is { agentId: chief_agent_id, subagentId: row.id }.
140
+ // resolveTargetTier sees subagentId set → returns "staff" tier without a chief lookup.
141
+ if (targetKind === "subagent") {
142
+ const { data } = await supabase
143
+ .from("agent_subagents")
144
+ .select("id, chief_agent_id")
145
+ .eq("user_id", userId)
146
+ .eq("id", targetId)
147
+ .maybeSingle();
148
+ if (!data) return null;
149
+ return {
150
+ agentId: (data.chief_agent_id as string | null) ?? null,
151
+ subagentId: (data.id as string | null) ?? null,
152
+ };
153
+ }
116
154
  const tbl =
117
155
  targetKind === "conversation" ? "conversations" :
118
156
  targetKind === "task" ? "tasks" : "scheduler_events";
package/src/tools.ts CHANGED
@@ -748,7 +748,16 @@ async function handleCreateTask(
748
748
  // INSERTed the raw input then reassigned insertData.start_date afterward,
749
749
  // which left the DB row with the unconverted value and the response with
750
750
  // the converted one — confusing and unsafe for the scheduler.
751
- const rawStartDate = (params.start_date as string) || null;
751
+ //
752
+ // Cycle 12 fix: when delegating to a staff (subagent_id present) without
753
+ // an explicit start_date, default to now + 5s so the scheduler_event auto-
754
+ // create branch below kicks in. Without this, the task sat PENDING forever
755
+ // because processDirectTasks' date-string filter also skips it (separate
756
+ // bug, fixed in task-dispatcher v21). The 5s buffer ensures the safety
757
+ // net at line ~805 doesn't trip and shift the run to +60s.
758
+ const explicitStartDate = (params.start_date as string) || null;
759
+ const rawStartDate = explicitStartDate
760
+ ?? (params.subagent_id ? new Date(Date.now() + 5_000).toISOString() : null);
752
761
  const normalized = rawStartDate
753
762
  ? normalizeStartDate(rawStartDate, params.scheduled_time as string | undefined, TZ_OFFSET_HOURS)
754
763
  : null;
@@ -5116,9 +5125,9 @@ function registerSOPOps(
5116
5125
  `- "delete": Remove SOP. Required: sop_id\n` +
5117
5126
  `- "list_subagents": List subagents for a chief. Required: chief_agent_id. (Provided here for convenience when scoping SOP authoring; team management lives in OFIERE_AGENT_OPS.)\n` +
5118
5127
  `- "apply_template": Create SOP from template. Required: agent_id, template_id. Optional: title, department\n` +
5119
- `- "propose_attach": Propose attaching SOPs to a run target (conversation/task/scheduler_event). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit.\n` +
5128
+ `- "propose_attach": Propose attaching SOPs to a target (conversation/task/scheduler_event/subagent). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit. Use target_kind="subagent" to attach SOPs to the staff PROFILE itself (applies to every dispatch); use task/conversation/scheduler_event for one-off run-scoped attach.\n` +
5120
5129
  `- "commit_attach": Commit a proposed attachment. Required: target_kind, target_id, doc_ids[], confirmation_token (from propose_attach). Only call AFTER user approves the token cost.\n` +
5121
- `Tier rule: SOPs only attach to targets whose assigned agent is Staff. Use OFIERE_FRAMEWORK_OPS for c-suite targets.\n\n` +
5130
+ `Tier rule: SOPs only attach to targets whose assigned agent is Staff (or to a subagent profile directly). Use OFIERE_FRAMEWORK_OPS for c-suite targets.\n\n` +
5122
5131
  `sop_data structure (JSON object):\n` +
5123
5132
  `{\n` +
5124
5133
  ` title: string,\n` +
@@ -5143,8 +5152,8 @@ function registerSOPOps(
5143
5152
  agent_id: { type: "string", description: "Agent ID (required for create, list filter, apply_template)" },
5144
5153
  chief_agent_id: { type: "string", description: "Chief agent ID (required for list_subagents)" },
5145
5154
  template_id: { type: "string", description: "Template ID (required for apply_template)" },
5146
- target_kind: { type: "string", enum: ["conversation", "task", "scheduler_event"], description: "Run target kind (for propose_attach/commit_attach)" },
5147
- target_id: { type: "string", description: "Run target id (for propose_attach/commit_attach)" },
5155
+ target_kind: { type: "string", enum: ["conversation", "task", "scheduler_event", "subagent"], description: "Target kind (for propose_attach/commit_attach). 'subagent' writes to staff PROFILE (persists across all dispatches); others are run-scoped." },
5156
+ target_id: { type: "string", description: "Target id (for propose_attach/commit_attach). For target_kind='subagent', this is the agent_subagents row id." },
5148
5157
  doc_ids: { type: "array", items: { type: "string" }, description: "SOP ids to attach (for propose_attach/commit_attach)" },
5149
5158
  confirmation_token: { type: "string", description: "Token returned by propose_attach. Required for commit_attach." },
5150
5159
  title: { type: "string", description: "SOP title" },
@@ -5656,7 +5665,7 @@ function registerFrameworkOps(
5656
5665
  `- "get": Get full framework details. Required: framework_id\n` +
5657
5666
  `- "update": Modify framework. Required: framework_id. Optional: title, content, status, department, category\n` +
5658
5667
  `- "delete": Remove framework. Required: framework_id\n` +
5659
- `- "propose_attach": Propose attaching Frameworks to a run target. Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit.\n` +
5668
+ `- "propose_attach": Propose attaching Frameworks to a target (conversation/task/scheduler_event). Returns token cost + confirmation_token. Required: target_kind, target_id, doc_ids[]. The user MUST be asked to approve before commit. Frameworks are c-suite only — they cannot be attached to staff subagents.\n` +
5660
5669
  `- "commit_attach": Commit a proposed attachment. Required: target_kind, target_id, doc_ids[], confirmation_token (from propose_attach). Only call AFTER user approves the token cost.\n` +
5661
5670
  `Tier rule: Frameworks only attach to targets whose assigned agent is C-Suite. Use OFIERE_SOP_OPS for staff targets.\n\n` +
5662
5671
  `content: A JSON string containing the full framework body. Example:\n` +
package/tsconfig.json CHANGED
@@ -1,23 +1,23 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": ["ES2022"],
7
- "esModuleInterop": true,
8
- "forceConsistentCasingInFileNames": true,
9
- "strict": true,
10
- "noImplicitAny": true,
11
- "skipLibCheck": true,
12
- "resolveJsonModule": true,
13
- "noEmit": false,
14
- "outDir": "dist",
15
- "rootDir": ".",
16
- "declaration": false,
17
- "sourceMap": false,
18
- "allowImportingTsExtensions": false,
19
- "isolatedModules": true
20
- },
21
- "include": ["index.ts", "src/**/*.ts"],
22
- "exclude": ["node_modules", "dist"]
23
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "strict": true,
10
+ "noImplicitAny": true,
11
+ "skipLibCheck": true,
12
+ "resolveJsonModule": true,
13
+ "noEmit": false,
14
+ "outDir": "dist",
15
+ "rootDir": ".",
16
+ "declaration": false,
17
+ "sourceMap": false,
18
+ "allowImportingTsExtensions": false,
19
+ "isolatedModules": true
20
+ },
21
+ "include": ["index.ts", "src/**/*.ts"],
22
+ "exclude": ["node_modules", "dist"]
23
+ }