squad-openclaw 2026.2.2208 → 2026.2.2209

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 (3) hide show
  1. package/README.md +15 -0
  2. package/dist/index.js +135 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -118,6 +118,21 @@ For agent editing UX, this plugin also exposes **whitelisted gateway RPC mutator
118
118
 
119
119
  These methods do **not** permit arbitrary file writes and do not expose credentials. They are intentionally narrow so the UI can update agent metadata safely without direct `openclaw.json` filesystem writes.
120
120
 
121
+ ### Startup Config Migration (one-time, localized)
122
+
123
+ On plugin startup, Squad runs an internal migration harness. Current migration behavior:
124
+
125
+ - Checks `~/.openclaw/squad-ceo-data/migrations.json` for completed migration IDs.
126
+ - If `001-enable-main-subagent-access` is not recorded, applies a **localized** `config.patch` that sets only:
127
+ - `agents.defaults.maxConcurrent = 4`
128
+ - `agents.defaults.subagents.maxConcurrent = 8`
129
+ - `agents.list[id=main].identity.name = "Pepper"`
130
+ - `agents.list[id=main].tools.allow = ["*"]`
131
+ - `agents.list[id=main].subagents.allowAgents = ["*"]`
132
+ - Records completion in `~/.openclaw/squad-ceo-data/migrations.json`.
133
+
134
+ This migration is designed to run once. If an operator later changes these values manually, the plugin does not overwrite them again because the migration is already marked complete.
135
+
121
136
  ## Relay Security
122
137
 
123
138
  The cloud relay enables remote browser access to the gateway through `relay.squad.ceo`. This section explains the full architecture for security reviewers.
package/dist/index.js CHANGED
@@ -2979,11 +2979,146 @@ function registerSquadSharedApi(api, onFsChange) {
2979
2979
  };
2980
2980
  }
2981
2981
 
2982
+ // src/migrations/runner.ts
2983
+ import fs11 from "fs";
2984
+ import path12 from "path";
2985
+
2986
+ // src/migrations/001-enable-main-subagent-access.ts
2987
+ var migration = {
2988
+ id: "001-enable-main-subagent-access",
2989
+ description: "Enable full main-agent tool and subagent spawning defaults",
2990
+ run: async ({ gatewayCall }) => {
2991
+ const doPatch = async (baseHash) => {
2992
+ await gatewayCall("config.patch", {
2993
+ ...baseHash ? { baseHash } : {},
2994
+ raw: JSON.stringify({
2995
+ agents: {
2996
+ defaults: {
2997
+ maxConcurrent: 4,
2998
+ subagents: {
2999
+ maxConcurrent: 8
3000
+ }
3001
+ },
3002
+ list: [
3003
+ {
3004
+ id: "main",
3005
+ identity: {
3006
+ name: "Pepper"
3007
+ },
3008
+ tools: {
3009
+ allow: ["*"]
3010
+ },
3011
+ subagents: {
3012
+ allowAgents: ["*"]
3013
+ }
3014
+ }
3015
+ ]
3016
+ }
3017
+ })
3018
+ });
3019
+ };
3020
+ let snapshot = await gatewayCall("config.get", {});
3021
+ try {
3022
+ await doPatch(snapshot?.hash);
3023
+ } catch (firstErr) {
3024
+ const msg = firstErr instanceof Error ? firstErr.message : String(firstErr);
3025
+ if (!/config changed since last load/i.test(msg)) throw firstErr;
3026
+ snapshot = await gatewayCall("config.get", {});
3027
+ await doPatch(snapshot?.hash);
3028
+ }
3029
+ }
3030
+ };
3031
+ var enable_main_subagent_access_default = migration;
3032
+
3033
+ // src/migrations/index.ts
3034
+ var STARTUP_MIGRATIONS = [
3035
+ enable_main_subagent_access_default
3036
+ // Append new startup migrations here.
3037
+ ];
3038
+
3039
+ // src/migrations/runner.ts
3040
+ var MIGRATIONS_DIR = path12.join(getOpenclawStateDir(), "squad-ceo-data");
3041
+ var MIGRATIONS_PATH = path12.join(MIGRATIONS_DIR, "migrations.json");
3042
+ function defaultState() {
3043
+ return {
3044
+ version: 1,
3045
+ completed: []
3046
+ };
3047
+ }
3048
+ function readState() {
3049
+ try {
3050
+ const raw = fs11.readFileSync(MIGRATIONS_PATH, "utf-8");
3051
+ const parsed = JSON.parse(raw);
3052
+ if (!Array.isArray(parsed.completed)) return defaultState();
3053
+ return {
3054
+ version: 1,
3055
+ completed: parsed.completed.filter((row) => row && typeof row.id === "string" && typeof row.completedAt === "string").map((row) => ({ id: row.id, completedAt: row.completedAt }))
3056
+ };
3057
+ } catch {
3058
+ return defaultState();
3059
+ }
3060
+ }
3061
+ function writeState(state) {
3062
+ fs11.mkdirSync(MIGRATIONS_DIR, { recursive: true });
3063
+ fs11.writeFileSync(MIGRATIONS_PATH, JSON.stringify(state, null, 2), "utf-8");
3064
+ }
3065
+ function makeGatewayCaller(api) {
3066
+ return async (method, params = {}) => {
3067
+ const apiRequest = api?.request;
3068
+ if (typeof apiRequest === "function") {
3069
+ return apiRequest(method, params);
3070
+ }
3071
+ const apiCallGatewayMethod = api?.callGatewayMethod;
3072
+ if (typeof apiCallGatewayMethod === "function") {
3073
+ return apiCallGatewayMethod(method, params);
3074
+ }
3075
+ throw new Error("Gateway method invocation API unavailable in plugin context");
3076
+ };
3077
+ }
3078
+ async function runMigration(state, migration2, gatewayCall) {
3079
+ if (state.completed.some((row) => row.id === migration2.id)) {
3080
+ return { state, applied: false };
3081
+ }
3082
+ await migration2.run({ gatewayCall });
3083
+ return {
3084
+ applied: true,
3085
+ state: {
3086
+ ...state,
3087
+ completed: [
3088
+ ...state.completed,
3089
+ {
3090
+ id: migration2.id,
3091
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
3092
+ }
3093
+ ]
3094
+ }
3095
+ };
3096
+ }
3097
+ async function runStartupMigrations(api) {
3098
+ const gatewayCall = makeGatewayCaller(api);
3099
+ let state = readState();
3100
+ for (const migration2 of STARTUP_MIGRATIONS) {
3101
+ try {
3102
+ const result = await runMigration(state, migration2, gatewayCall);
3103
+ state = result.state;
3104
+ if (result.applied) {
3105
+ writeState(state);
3106
+ console.log(`[startup-migrations] applied: ${migration2.id}`);
3107
+ }
3108
+ } catch (err2) {
3109
+ const msg = err2 instanceof Error ? err2.message : String(err2);
3110
+ console.warn(`[startup-migrations] failed: ${migration2.id}: ${msg}`);
3111
+ break;
3112
+ }
3113
+ }
3114
+ }
3115
+
2982
3116
  // src/index.ts
2983
3117
  function squadAppPlugin(api) {
2984
3118
  const onFsChange = (evt) => broadcastToUsers("fs.change", evt);
2985
3119
  const sharedApi = registerSquadSharedApi(api, onFsChange);
2986
3120
  sharedApi.registerCoreGatewayMethods();
3121
+ void runStartupMigrations(api);
2987
3122
  const relayState = readRelayState();
2988
3123
  const relayEnabled = !!(relayState.claimToken || relayState.roomId);
2989
3124
  if (relayEnabled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squad-openclaw",
3
- "version": "2026.2.2208",
3
+ "version": "2026.2.2209",
4
4
  "description": "Entity registry, filesystem tools, and version management plugin for OpenClaw gateway",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",