Skip to content

feat(store): migrate local state to typed ids#245

Merged
RussellLuo merged 3 commits into
OpenCSGs:mainfrom
xxx7xxxx:dev
Jun 26, 2026
Merged

feat(store): migrate local state to typed ids#245
RussellLuo merged 3 commits into
OpenCSGs:mainfrom
xxx7xxxx:dev

Conversation

@xxx7xxxx

@xxx7xxxx xxx7xxxx commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Consolidate durable local store data into ~/.csgclaw/state.json with auth.opencsg, model_providers.items, agents.model_defaults, agents.items, and participants.items.
  • Keep IM topology separate and lightweight in ~/.csgclaw/im/state.json with current_user_id, IM users, and room membership only.
  • Store room message history in im/sessions/*.jsonl and thread context in im/threads/<room_id>/<root_message_id>.json.
  • Migrate owned local identities and directory names to immutable typed IDs such as agent-*, pt-*, user-*, room-*, team-*, msg-*, task-*, and approval-*.
  • Update API, web, and CLI surfaces around model_config, IM-user avatars, user-based IM membership, MODEL table output, and full CLI table values without truncation.

Current State Shape

The current migrated root store has these top-level sections:

{
  "version": 1,
  "auth": {
    "opencsg": {
      "tokens": "<redacted>",
      "account": "<redacted>",
      "last_refresh": "<redacted>",
      "ai_gateway_builtin_api_key": "<redacted>"
    }
  },
  "model_providers": {
    "items": {
      "claude_code": "<provider>",
      "codex": "<provider>",
      "csghub-lite": "<provider>",
      "default": "<provider>",
      "opencsg": "<provider>"
    }
  },
  "agents": {
    "model_defaults": {
      "model_provider_id": "codex",
      "model_id": "gpt-5.5",
      "reasoning_effort": "medium"
    },
    "items": [
      {
        "id": "agent-zoyz2k",
        "name": "dev",
        "role": "worker",
        "runtime": {
          "kind": "codex",
          "state": "running",
          "sandbox_id": "<sandbox-id>"
        },
        "model_config": {
          "model_provider_id": "codex",
          "model_id": "gpt-5.5",
          "reasoning_effort": "medium"
        }
      },
      {
        "id": "agent-manager",
        "name": "manager",
        "role": "manager",
        "runtime": {
          "kind": "picoclaw_sandbox",
          "state": "running",
          "sandbox_id": "<sandbox-id>"
        },
        "model_config": {
          "model_provider_id": "codex",
          "model_id": "gpt-5.5",
          "reasoning_effort": "medium"
        }
      }
    ]
  },
  "participants": {
    "items": [
      {
        "id": "pt-admin",
        "name": "admin",
        "type": "human",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-admin",
        "lifecycle_status": "active",
        "mentionable": true
      },
      {
        "id": "pt-manager",
        "name": "manager",
        "type": "agent",
        "agent_id": "agent-manager",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-manager",
        "lifecycle_status": "active",
        "mentionable": true
      },
      {
        "id": "pt-manager-ec18f310",
        "name": "manager",
        "type": "agent",
        "agent_id": "agent-manager",
        "channel": "feishu",
        "channel_user_kind": "app_id",
        "lifecycle_status": "active",
        "mentionable": true
      }
    ]
  }
}

The current migrated IM state is intentionally smaller and user-based:

{
  "current_user_id": "user-admin",
  "users": [
    {
      "id": "user-admin",
      "name": "admin",
      "role": "admin",
      "avatar": "avatar/pic-8.png",
      "is_online": true
    },
    {
      "id": "user-zoyz2k",
      "name": "dev",
      "role": "worker",
      "avatar": "avatar/cartoon-8.png",
      "is_online": true
    },
    {
      "id": "user-manager",
      "name": "manager",
      "role": "manager",
      "avatar": "avatar/cartoon-7.png",
      "is_online": true
    }
  ],
  "rooms": [
    {
      "id": "room-1782371895502009000",
      "title": "all-members",
      "members": [
        "user-admin",
        "user-zoyz2k",
        "user-manager",
        "user-dahym7",
        "user-eczpyv"
      ],
      "messages": "sessions/room-1782371895502009000.jsonl",
      "threads": "<lightweight thread refs>"
    },
    {
      "id": "room-1782371840126766000",
      "title": "dev",
      "is_direct": true,
      "members": ["user-admin", "user-zoyz2k"],
      "messages": "sessions/room-1782371840126766000.jsonl",
      "threads": "<lightweight thread refs>"
    }
  ]
}

Full redacted examples for the current local ~/.csgclaw/state.json and ~/.csgclaw/im/state.json are in this PR comment:

#245 (comment)

Store Layout

  • ~/.csgclaw/state.json: durable root app state, OpenCSG auth, model providers, compact agents, and participants.
  • ~/.csgclaw/agents/<agent-id>/: agent runtime directories keyed by immutable agent-* IDs, not display names.
  • ~/.csgclaw/im/state.json: IM users and room topology keyed by immutable user-* and room-* IDs.
  • ~/.csgclaw/im/sessions/<room_id>.jsonl: message history.
  • ~/.csgclaw/im/threads/<room_id>/<root_message_id>.json: heavy thread context.
  • ~/.csgclaw/cliproxy-auth/: CLIProxyAPI-owned auth files moved out of the generic auth/ directory.

CLI And API Impact

  • Agent JSON uses model_config as the primary model selection contract.
  • Agent tables show MODEL, related participant names and IDs, and full values without truncation.
  • User tables show ID NAME ROLE ONLINE; local IM handles are removed.
  • Room membership, message senders, mentions, and thread refs are based on user-* IDs.
  • Participants remain channel-delivery bindings for CSGClaw and Feishu, not IM room members.

Notice

  • This migration keeps full-store backup behavior before rewriting local data.
  • Migration compatibility code can be removed later after this state shape has been universally adopted.

Validation

  • Validated locally end to end after rebasing onto current main.

@xxx7xxxx xxx7xxxx marked this pull request as draft June 25, 2026 09:39
@xxx7xxxx xxx7xxxx marked this pull request as ready for review June 25, 2026 11:12
@xxx7xxxx xxx7xxxx requested a review from RussellLuo June 25, 2026 11:12
@xxx7xxxx

xxx7xxxx commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Current migrated state examples

Generated from the current local migrated store. Secret-bearing auth, token, and API key fields are redacted.

~/.csgclaw/state.json

{
  "agents": {
    "model_defaults": {
      "model_provider_id": "codex",
      "model_id": "gpt-5.5",
      "reasoning_effort": "medium"
    },
    "items": [
      {
        "created_at": "2026-06-25T08:32:01.672018Z",
        "description": "Builtin PicoClaw worker template",
        "id": "agent-zoyz2k",
        "model_config": {
          "model_provider_id": "codex",
          "model_id": "gpt-5.5",
          "reasoning_effort": "medium"
        },
        "name": "dev",
        "role": "worker",
        "runtime": {
          "kind": "codex",
          "sandbox_id": "019efde8-525e-7c22-bcdd-fe8524fd5cfe",
          "state": "running"
        },
        "updated_at": "2026-06-25T08:32:01.672018Z"
      },
      {
        "created_at": "2026-06-25T08:32:12.385531092Z",
        "description": "Builtin PicoClaw worker template",
        "id": "agent-dahym7",
        "image": "opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq/picoclaw:2026.6.23",
        "model_config": {
          "model_provider_id": "opencsg",
          "model_id": "qwen3.6-plus",
          "reasoning_effort": "medium"
        },
        "name": "qa",
        "role": "worker",
        "runtime": {
          "kind": "picoclaw_sandbox",
          "sandbox_id": "08ee0f4738e90f6edb86b7cc1cf8412b010f7790873cdb372954d8bf733f3a5d",
          "state": "running"
        },
        "updated_at": "2026-06-25T08:32:12.385531092Z"
      },
      {
        "created_at": "2026-06-25T08:32:20.488932596Z",
        "description": "Builtin PicoClaw worker template",
        "id": "agent-eczpyv",
        "image": "opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq/picoclaw:2026.6.23",
        "model_config": {
          "model_provider_id": "default",
          "model_id": "deepseek-v4-flash",
          "reasoning_effort": "medium"
        },
        "name": "ux",
        "role": "worker",
        "runtime": {
          "kind": "picoclaw_sandbox",
          "sandbox_id": "1715aa5879db702ba048b04a3a455e7eb558f91f580d6c38f91257f1ef3a70ee",
          "state": "running"
        },
        "updated_at": "2026-06-25T08:32:20.488932596Z"
      },
      {
        "created_at": "2026-06-26T08:37:10.681757508Z",
        "id": "agent-manager",
        "image": "opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq/picoclaw:2026.6.23",
        "model_config": {
          "model_provider_id": "codex",
          "model_id": "gpt-5.5",
          "reasoning_effort": "medium"
        },
        "name": "manager",
        "role": "manager",
        "runtime": {
          "kind": "picoclaw_sandbox",
          "sandbox_id": "0463be1cac2b94cff4be8f02a74e44678cafda592805eab491c311c33657d12a",
          "state": "running"
        },
        "updated_at": "2026-06-26T08:37:10.681757508Z"
      }
    ]
  },
  "auth": {
    "opencsg": {
      "account": {
        "avatar": "<redacted>",
        "base_url": "<redacted>",
        "logged_in_at": "<redacted>",
        "portal_url": "<redacted>",
        "user_id": "<redacted>",
        "user_uuid": "<redacted>"
      },
      "ai_gateway_builtin_api_key": "<redacted>",
      "last_refresh": "2026-06-25T07:16:08.915164Z",
      "tokens": "<redacted>"
    }
  },
  "model_providers": {
    "items": {
      "claude_code": {
        "models": [
          "claude-opus-4-20250514",
          "claude-sonnet-4-20250514",
          "claude-opus-4-7",
          "claude-opus-4-6",
          "claude-sonnet-4-6",
          "claude-opus-4-5-20251101",
          "claude-haiku-4-5-20251001",
          "claude-sonnet-4-5-20250929",
          "claude-opus-4-1-20250805",
          "claude-3-7-sonnet-20250219",
          "claude-3-5-haiku-20241022"
        ],
        "status": "connected",
        "message": "connected",
        "last_checked_at": "2026-06-26T08:40:09Z"
      },
      "codex": {
        "models": [
          "gpt-5.5",
          "gpt-5.4",
          "gpt-5.4-mini",
          "gpt-5.3-codex-spark",
          "gpt-image-2",
          "codex-auto-review"
        ],
        "status": "connected",
        "message": "connected",
        "last_checked_at": "2026-06-26T08:40:09Z"
      },
      "csghub-lite": {
        "base_url": "http://127.0.0.1:11435/v1",
        "api_key": "<redacted>",
        "models": [
          "gpt-4.1-mini",
          "qwen3.6-plus",
          "Qwen3-0.6B-GGUF",
          "Qwen/Qwen-Image-2512:s-qwen-qwen-image-2512-6byf",
          "FunAudioLLM/Fun-ASR-Nano-2512:s-aiwizards-fun-asr-nano-2512-6bkg",
          "afrideva/Qwen2-0.5B-Instruct-GGUF:fh23aijhzx8g",
          "glm-5.1",
          "glm-5",
          "deepseek-v4-flash",
          "Qwen/Qwen3.5-35B-A3B-FP8:s-qwen-qwen3-5-35b-a3b-fp8-6dp9",
          "Qwen/Qwen3Guard-Gen-0.6B:s-qwen-qwen3guard-gen-0-6b-6ac8",
          "minimax-m2.7",
          "MiniMax-M2.5",
          "gemini-2.5-flash"
        ],
        "status": "connected",
        "message": "connected",
        "last_checked_at": "2026-06-26T08:40:08Z"
      },
      "default": {
        "display_name": "DeepSeek",
        "base_url": "https://api.deepseek.com",
        "api_key": "<redacted>",
        "models": [
          "deepseek-v4-pro",
          "deepseek-v4-flash"
        ],
        "status": "connected",
        "message": "connected",
        "last_checked_at": "2026-06-26T08:40:09Z"
      },
      "opencsg": {
        "models": [
          "gpt-4.1-mini",
          "qwen3.6-plus",
          "qwen3-asr-flash",
          "Qwen/Qwen-Image-2512:s-qwen-qwen-image-2512-6byf",
          "FunAudioLLM/Fun-ASR-Nano-2512:s-aiwizards-fun-asr-nano-2512-6bkg",
          "afrideva/Qwen2-0.5B-Instruct-GGUF:fh23aijhzx8g",
          "glm-5.1",
          "glm-5",
          "deepseek-v4-flash",
          "Qwen/Qwen3.5-35B-A3B-FP8:s-qwen-qwen3-5-35b-a3b-fp8-6dp9",
          "Qwen/Qwen3Guard-Gen-0.6B:s-qwen-qwen3guard-gen-0-6b-6ac8",
          "minimax-m2.7",
          "MiniMax-M2.5",
          "gemini-2.5-flash"
        ],
        "status": "connected",
        "message": "connected",
        "last_checked_at": "2026-06-26T08:40:08Z"
      }
    }
  },
  "participants": {
    "items": [
      {
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-admin",
        "created_at": "2026-06-25T07:15:43.558458Z",
        "id": "pt-admin",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "admin",
        "type": "human",
        "updated_at": "2026-06-25T07:15:43.558458Z"
      },
      {
        "agent_id": "agent-manager",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-manager",
        "created_at": "2026-06-25T07:15:43.944404385Z",
        "id": "pt-manager",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "manager",
        "type": "agent",
        "updated_at": "2026-06-25T07:15:44.151153Z"
      },
      {
        "agent_id": "agent-zoyz2k",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-zoyz2k",
        "created_at": "2026-06-25T07:17:20.12772Z",
        "id": "pt-zoyz2k",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "dev",
        "type": "agent",
        "updated_at": "2026-06-25T07:17:20.12772Z"
      },
      {
        "agent_id": "agent-dahym7",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-dahym7",
        "created_at": "2026-06-25T07:17:38.493856Z",
        "id": "pt-dahym7",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "qa",
        "type": "agent",
        "updated_at": "2026-06-25T07:17:38.493856Z"
      },
      {
        "agent_id": "agent-eczpyv",
        "channel": "csgclaw",
        "channel_user_kind": "local_user_id",
        "channel_user_ref": "user-eczpyv",
        "created_at": "2026-06-25T07:17:53.681744Z",
        "id": "pt-eczpyv",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "ux",
        "type": "agent",
        "updated_at": "2026-06-25T07:17:53.681744Z"
      },
      {
        "channel": "feishu",
        "channel_user_kind": "open_id",
        "channel_user_ref": "ou_92218e0eae84eeabe48ba6ab065fe614",
        "created_at": "2026-06-25T08:31:51.998178Z",
        "id": "pt-admin-edbf51fd",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "admin",
        "type": "human",
        "updated_at": "2026-06-25T08:32:20.082195Z"
      },
      {
        "agent_id": "agent-manager",
        "channel": "feishu",
        "channel_app_config": {
          "app_id": "cli_aab91ae119b85ccd",
          "app_secret": "<redacted>"
        },
        "channel_user_kind": "app_id",
        "created_at": "2026-06-25T08:31:52.132957Z",
        "id": "pt-manager-ec18f310",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "manager",
        "type": "agent",
        "updated_at": "2026-06-25T08:31:52.132957Z"
      },
      {
        "agent_id": "agent-zoyz2k",
        "channel": "feishu",
        "channel_app_config": {
          "app_id": "cli_aab8af207ebb5cd6",
          "app_secret": "<redacted>"
        },
        "channel_user_kind": "app_id",
        "created_at": "2026-06-25T08:32:00.947381Z",
        "id": "pt-zoyz2k-5905c292",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "dev",
        "type": "agent",
        "updated_at": "2026-06-25T08:32:00.947381Z"
      },
      {
        "agent_id": "agent-dahym7",
        "channel": "feishu",
        "channel_app_config": {
          "app_id": "cli_aab82a8e6c385ce1",
          "app_secret": "<redacted>"
        },
        "channel_user_kind": "app_id",
        "created_at": "2026-06-25T08:32:12.104802Z",
        "id": "pt-dahym7-2345ac42",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "qa",
        "type": "agent",
        "updated_at": "2026-06-25T08:32:12.104802Z"
      },
      {
        "agent_id": "agent-eczpyv",
        "channel": "feishu",
        "channel_app_config": {
          "app_id": "cli_aab919f448ba9cd5",
          "app_secret": "<redacted>"
        },
        "channel_user_kind": "app_id",
        "created_at": "2026-06-25T08:32:20.246691Z",
        "id": "pt-eczpyv-555d5c54",
        "lifecycle_status": "active",
        "mentionable": true,
        "name": "ux",
        "type": "agent",
        "updated_at": "2026-06-25T08:32:20.246691Z"
      }
    ]
  },
  "version": 1
}

~/.csgclaw/im/state.json

{
  "current_user_id": "user-admin",
  "rooms": [
    {
      "id": "room-1782371895502009000",
      "members": [
        "user-admin",
        "user-zoyz2k",
        "user-manager",
        "user-dahym7",
        "user-eczpyv"
      ],
      "messages": "sessions/room-1782371895502009000.jsonl",
      "subtitle": "",
      "threads": [
        {
          "created_at": "2026-06-25T07:18:23.994101Z",
          "root_message_id": "msg-1782371903992884000",
          "summary": {
            "after_count": 1,
            "before_count": 2,
            "message_count": 4,
            "root_excerpt": "Hey there! 👋 I see you're pinging the team — **@dev**, **@manager**, **@qa**, **@ux**. I'm **PicoClaw 🦞**, your default assistant here. If you've got a task or "
          }
        },
        {
          "created_at": "2026-06-25T07:18:39.214381Z",
          "root_message_id": "msg-1782371905995156000",
          "summary": {
            "after_count": 2,
            "before_count": 3,
            "message_count": 6,
            "root_excerpt": "Using `superpowers:using-superpowers` to follow the required skill workflow before responding."
          }
        },
        {
          "created_at": "2026-06-25T07:18:43.878271Z",
          "root_message_id": "msg-1782371911792799000",
          "summary": {
            "after_count": 2,
            "before_count": 4,
            "message_count": 7,
            "root_excerpt": "我在,PicoClaw 🦞(CSGClaw manager)上线。 你刚刚提到了 dev / manager / qa / ux,看起来像是想召集团队,但还没有具体任务。 我可以帮你: - 分配任务给现有 worker:如“让 dev 修复登录 bug,qa 做回归测试” - 组织多角色协作:如“ux 先出方案,dev"
          }
        },
        {
          "created_at": "2026-06-25T07:18:51.414783Z",
          "root_message_id": "msg-1782371913450463000",
          "summary": {
            "after_count": 1,
            "before_count": 5,
            "message_count": 7,
            "root_excerpt": "Hey! I see you've mentioned @dev @manager @qa @ux. What would you like to do with these roles? I can help with: - Dispatching tasks to specific team members - S"
          }
        }
      ],
      "title": "all-members"
    },
    {
      "description": "Bootstrap room for admin and dev.",
      "id": "room-1782371840126766000",
      "is_direct": true,
      "members": [
        "user-admin",
        "user-zoyz2k"
      ],
      "messages": "sessions/room-1782371840126766000.jsonl",
      "subtitle": "",
      "threads": [
        {
          "created_at": "2026-06-25T07:18:10.973653Z",
          "root_message_id": "msg-1782371890972552000",
          "summary": {
            "after_count": 0,
            "before_count": 2,
            "message_count": 3,
            "root_excerpt": ""
          }
        }
      ],
      "title": "dev"
    },
    {
      "description": "Bootstrap room for admin and qa.",
      "id": "room-1782371858492760000",
      "is_direct": true,
      "members": [
        "user-admin",
        "user-dahym7"
      ],
      "messages": "sessions/room-1782371858492760000.jsonl",
      "subtitle": "",
      "title": "qa"
    },
    {
      "description": "Bootstrap room for admin and manager.",
      "id": "room-1782371743557013000",
      "is_direct": true,
      "members": [
        "user-admin",
        "user-manager"
      ],
      "messages": "sessions/room-1782371743557013000.jsonl",
      "subtitle": "",
      "title": "admin & manager"
    },
    {
      "description": "Bootstrap room for admin and ux.",
      "id": "room-1782371873680388000",
      "is_direct": true,
      "members": [
        "user-admin",
        "user-eczpyv"
      ],
      "messages": "sessions/room-1782371873680388000.jsonl",
      "subtitle": "",
      "title": "ux"
    }
  ],
  "users": [
    {
      "accent_hex": "#dc2626",
      "avatar": "avatar/pic-8.png",
      "created_at": "0001-01-01T00:00:00Z",
      "description": "Human operator. Agents can @admin to ask clarifying questions, request confirmation, and double-check important decisions before continuing.",
      "id": "user-admin",
      "is_online": true,
      "name": "admin",
      "role": "admin"
    },
    {
      "accent_hex": "#db2777",
      "avatar": "avatar/cartoon-8.png",
      "created_at": "2026-06-25T07:17:20.126761Z",
      "id": "user-zoyz2k",
      "is_online": true,
      "name": "dev",
      "role": "worker"
    },
    {
      "accent_hex": "#0f766e",
      "avatar": "avatar/cartoon-7.png",
      "created_at": "0001-01-01T00:00:00Z",
      "id": "user-manager",
      "is_online": true,
      "name": "manager",
      "role": "manager"
    },
    {
      "accent_hex": "#2563eb",
      "avatar": "avatar/3D-5.png",
      "created_at": "2026-06-25T07:17:38.492755Z",
      "id": "user-dahym7",
      "is_online": true,
      "name": "qa",
      "role": "worker"
    },
    {
      "accent_hex": "#059669",
      "avatar": "avatar/cartoon-2.png",
      "created_at": "2026-06-25T07:17:53.68038Z",
      "id": "user-eczpyv",
      "is_online": true,
      "name": "ux",
      "role": "worker"
    }
  ]
}

@xxx7xxxx xxx7xxxx marked this pull request as draft June 26, 2026 07:01
@xxx7xxxx

xxx7xxxx commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Update

  • Compact local store persistence around typed IDs, model_config, runtime-owned sandbox naming, and migration compatibility.
  • Update agent/API/frontend model config handling so agent model selection no longer persists or exposes the old profile shape as the primary contract.
  • Keep agent avatars sourced from linked IM users and adjust agent detail UI/tests around the compact state shape.
  • Rework CLI table rendering to use MODEL instead of PROFILE, preserve UTF-8 alignment, and stop truncating table output.
  • Extend migration, agent, runtime, API, frontend, and CLI tests for the new state shape and display behavior.

@xxx7xxxx xxx7xxxx marked this pull request as ready for review June 26, 2026 08:44
@xxx7xxxx

Copy link
Copy Markdown
Collaborator Author

@RussellLuo Fixed the review you gave me and did UTF-8 naming and other minor improvements.

@RussellLuo RussellLuo merged commit c3d7e82 into OpenCSGs:main Jun 26, 2026
2 checks passed
jialudev pushed a commit to jialudev/csgclaw that referenced this pull request Jun 29, 2026
- consolidate durable data into state.json and keep IM topology in a separate lightweight store
- move message history and thread context into dedicated session files
- migrate local entities and directories to immutable typed IDs
- update API, Web, and CLI surfaces for the new storage model
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants