Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
12 commits
Select commit Hold shift + click to select a range
15459c3
✨ 扩展仓迁移并新增 Elasticsearch 资产类型:移除旧 SDK/示例/oss,README 与 Makefile 改写,ES …
CodFrm Sep 29, 2026
ea09f48
✨ Elasticsearch 扩展新增 request/health/indices/mapping/search 工具、多资源策略分类…
CodFrm Sep 29, 2026
8693ccf
✨ Elasticsearch 扩展页面:侧栏索引列表、概览、索引标签(文档/Mapping/Settings)、控制台占位与前端工程
CodFrm Sep 29, 2026
d41a897
👷 扩展仓 CI:make ci 逐扩展跑 Go 测试、WASM 构建与前端检查,GitHub Actions 调用
CodFrm Sep 29, 2026
891dd56
✨ Elasticsearch 控制台:自定义 Monaco 语言高亮、光标处请求执行、关键字级自动提示(DSL 框共用)与按资产保存控制台标签
CodFrm Sep 29, 2026
ecd9398
🐛 Elasticsearch 策略:删除异步 / EQL / SQL 检索结果归为 admin,仅清除 scroll 与关闭 PIT 为…
CodFrm Sep 29, 2026
86c09a8
🐛 Elasticsearch 策略:_bulk/_msearch 按 ES 逐行配对(空行不再错位)、msearch 同读 index …
CodFrm Sep 29, 2026
dc89367
🐛 ES 扩展修正:认证方式选项本地化并默认 none、非法请求在分类阶段拒绝、indices 过滤 . 开头索引、DSL 编辑框固定高度…
CodFrm Sep 29, 2026
122c85a
🐛 Elasticsearch indices:以 . 开头的 pattern 照 ES 语义列出点号索引,不再被隐藏过滤吞掉;DSL 编…
CodFrm Sep 29, 2026
18dc736
🐛 Elasticsearch 策略:拒绝 ?source= 查询参数、_mtermvectors 按请求体索引分类、_downsampl…
CodFrm Sep 29, 2026
54480e3
🐛 Elasticsearch 控制台:同一资产的 console.load / console.save 按发起顺序串行,快速切回标签不…
CodFrm Sep 30, 2026
7f5cb72
📌 Elasticsearch 扩展依赖固定到已合并的 opskat(06493ac1),声明最低应用版本 1.14.1
CodFrm Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.26.0'

- name: Set up Node.js and pnpm
uses: pnpm/action-setup@v2
with:
version: '10'

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
# Lockfiles live per extension; setup-node only looks in the repo root by default.
cache-dependency-path: extensions/*/frontend/pnpm-lock.yaml

- name: Run CI
run: make ci
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Build artifacts
**/dist/
*.wasm
extensions/oss/backend/oss

# IDE
.idea/
Expand Down
42 changes: 39 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
EXT ?=

.PHONY: build clean
.PHONY: build test clean ci

build:
ifndef EXT
$(error EXT is required. Usage: make build EXT=oss)
$(error EXT is required. Usage: make build EXT=elasticsearch)
endif
$(MAKE) -C extensions/$(EXT) build

test:
ifndef EXT
$(error EXT is required. Usage: make test EXT=elasticsearch)
endif
$(MAKE) -C extensions/$(EXT) test

clean:
ifndef EXT
$(error EXT is required. Usage: make clean EXT=oss)
$(error EXT is required. Usage: make clean EXT=elasticsearch)
endif
$(MAKE) -C extensions/$(EXT) clean

ci:
@set -e; \
for ext_dir in extensions/*/; do \
if [ -f "$$ext_dir/Makefile" ]; then \
ext_name=$$(basename "$$ext_dir"); \
echo "=== CI for $$ext_name ==="; \
\
echo "Running Go tests..."; \
cd "$$ext_dir" && go test ./...; \
cd - > /dev/null; \
\
echo "Building WASM..."; \
cd "$$ext_dir" && GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o dist/main.wasm .; \
cd - > /dev/null; \
\
if [ -f "$$ext_dir/frontend/package.json" ]; then \
echo "Building frontend..."; \
cd "$$ext_dir/frontend" && pnpm install --frozen-lockfile; \
echo "Typechecking frontend..."; \
pnpm exec tsc --noEmit; \
echo "Running frontend tests..."; \
pnpm exec vitest run; \
echo "Building frontend bundle..."; \
pnpm build; \
cd - > /dev/null; \
fi; \
fi; \
done; \
echo "=== All checks passed ==="
238 changes: 33 additions & 205 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,227 +4,55 @@

<h1 align="center">OpsKat Extensions</h1>

<p align="center">A WebAssembly-based extension framework for the <a href="https://github.com/opskat/opskat">OpsKat</a> platform. Extensions are compiled to WASM and executed in a secure sandbox, combining Go backends with React frontends through a well-defined host interface.</p>
<p align="center">Source of the official <a href="https://github.com/opskat/opskat">OpsKat</a> extensions.</p>

<p align="center">
<img src="https://img.shields.io/badge/Go-1.23-00ADD8?style=for-the-badge&logo=go&logoColor=white" alt="Go">
&nbsp;
<img src="https://img.shields.io/badge/WASM-WASIP1-654FF0?style=for-the-badge&logo=webassembly&logoColor=white" alt="WASM">
&nbsp;
<img src="https://img.shields.io/badge/React-19-61DAFB?style=for-the-badge&logo=react&logoColor=white" alt="React">
</p>

## Architecture

```
┌─────────────────────────────────────────┐
│ OpsKat Host Application │
│ ┌───────────────┐ ┌────────────────┐ │
│ │ WASM Runtime │ │ Asset Config │ │
│ │ (tools/actions│ │ KV Store │ │
│ │ /policies) │ │ File & HTTP IO │ │
│ └───────────────┘ └────────────────┘ │
│ WASM Host Imports (ABI) │
└─────────────────────────────────────────┘
↕ WASM ABI
┌─────────────────────────────────────────┐
│ Extension (WASM Module) │
│ ┌───────────────┐ ┌────────────────┐ │
│ │ Go SDK │ │ User Code │ │
│ │ (opskat pkg) │ │ (tools/actions)│ │
│ └───────────────┘ └────────────────┘ │
└─────────────────────────────────────────┘
```
Each extension is a WASM guest built on the extension SDK that ships with OpsKat
(`github.com/opskat/opskat/pkg/extsdk`). For how to write one — manifest, asset
types, tools, policies, pages, testing — read
[`extensions/README.md`](https://github.com/opskat/opskat/blob/main/extensions/README.md)
in the OpsKat repository; it is not repeated here.

## Project Structure
## Layout

```
.
├── Makefile # Root build orchestrator
├── sdk/go/opskat/ # Go SDK for building extensions
├── extensions/
│ └── oss/ # S3-compatible object storage extension
│ ├── backend/ # Go → WASM
│ ├── frontend/ # React + Vite
│ ├── locales/ # i18n (en, zh-CN)
│ ├── manifest.json # Extension declaration
│ └── Makefile
└── examples/
└── echo/ # Minimal reference extension
├── backend/
├── frontend/
└── manifest.json
extensions/<name>/
go.mod # its own Go module: github.com/opskat/extensions/<name>
main.go ... # the guest; registrations live in init()
*_test.go # unit tests, driven through opskat.TestHost
manifest.json # name, version, hostABI, capability grants
SKILL.md # what the model reads about the extension (optional)
locales/ # en.json, zh-CN.json
frontend/ # page sources (optional)
Makefile # `build` produces dist/, `test` runs the tests
dist/ # build output, git-ignored
```

## Supported Extensions

### OSS Extension (`extensions/oss`)

A full-featured S3-compatible object storage manager. Works with AWS S3, MinIO, Aliyun OSS, and any S3-compatible service.

**Tools** (for AI invocation):

| Tool | Description |
|------|-------------|
| `list_buckets` | List all buckets |
| `list_objects` | List objects with pagination |
| `get_object_info` | Get object metadata |
| `download_object` | Download an object |
| `upload_object` | Upload an object |
| `copy_object` | Server-side copy |
| `move_object` | Move (copy + delete) |
| `delete_object` | Delete a single object |
| `delete_objects` | Batch delete |
| `presign_url` | Generate pre-signed URL |

**Actions** (for frontend UI):

| Action | Description |
|--------|-------------|
| `test_connection` | Validate asset configuration |
| `browse` | Navigate directories |
| `upload` / `download` | Transfer with progress events |
| `batch_delete` / `batch_copy` | Batch operations with progress |
| `get_presigned_url` | Generate share links |
| `search` | Prefix-based search |
| `preview` | Preview file content |
Current extensions: [`elasticsearch`](./extensions/elasticsearch).

**Policy groups**: Read-only, Read-Write, Full Access, with fine-grained action control (`list`, `read`, `write`, `delete`, `admin`).

### Echo Example (`examples/echo`)

A minimal reference extension demonstrating core SDK patterns: tool handling, action streaming, KV storage, logging, and policy checking.

## Key Concepts

| Concept | Description |
|---------|-------------|
| **Tool** | Stateless, synchronous operation invoked by AI |
| **Action** | Stateful, streaming operation invoked by frontend UI |
| **EventWriter** | Real-time event streaming from actions to frontend |
| **PolicyChecker** | Maps (tool, args) to (action, resource) for authorization |
| **IOHandle** | Abstracted file/HTTP I/O through the host |
| **Manifest** | JSON declaration of tools, actions, UI pages, and policies |

## Building

**Prerequisites**: [Go 1.23+](https://go.dev/), [Node.js 18+](https://nodejs.org/) with [pnpm](https://pnpm.io/)
## Build and test

```bash
# Build the OSS extension (backend WASM + frontend)
make build EXT=oss

# Or build manually
cd extensions/oss
make build
make build EXT=elasticsearch # -> extensions/elasticsearch/dist/
make test EXT=elasticsearch
```

Build steps:
1. Compile Go to WASM: `GOOS=wasip1 GOARCH=wasm go build -o dist/main.wasm .`
2. Build frontend with Vite: `pnpm install && pnpm build`
3. Copy `manifest.json` and `locales/` to `dist/`
Building needs Go with `GOOS=wasip1` support, and Node.js with pnpm for an extension
that has a `frontend/`. `dist/` is a complete extension directory: main.wasm,
manifest.json, SKILL.md when present, locales/, and the built page under frontend/
when the extension has one.

Output is in `extensions/oss/dist/`.
## Install locally

## Running the Dev Server
Either use "Install from directory" in the app's extension settings and pick
`extensions/<name>/dist`, or from a terminal:

```bash
make devserver EXT=oss
opsctl ext dev "$PWD/extensions/elasticsearch/dist"
```

This starts a local dev server that simulates the OpsKat host, loading your extension for interactive testing.

## Testing

Run unit tests (no WASM compilation required):

```bash
# Test OSS extension
cd extensions/oss/backend && go test -v ./...

# Test echo example
cd examples/echo/backend && go test -v ./...

# Test SDK
cd sdk/go/opskat && go test -v ./...
```

The SDK provides `TestHost` for simulating the host environment in tests:

```go
func TestMyTool(t *testing.T) {
th := opskat.NewTestHost(
opskat.WithAssetConfig("my-asset", myConfig),
opskat.WithMockHTTP(mockHandler),
)
defer th.Close()

result, err := th.CallTool("my_tool", map[string]any{"key": "value"})
// assert result
}
```

## Developing a New Extension

1. **Create the directory structure**:
```
extensions/my-ext/
├── backend/
│ ├── main.go
│ └── go.mod
├── frontend/
│ └── index.js (or use Vite for TypeScript)
├── manifest.json
└── Makefile
```

2. **Register handlers** in `main.go`:
```go
package main

import "github.com/opskat/extensions/sdk/go/opskat"

func main() {
opskat.RegisterTool("my_tool", handleMyTool)
opskat.RegisterAction("my_action", handleMyAction)
opskat.RegisterPolicyChecker(checkPolicy)
opskat.Run()
}
```

3. **Write frontend** using host-provided React:
```js
const { React } = window.__OPSKAT_EXT__;

export function MyPage({ assetId }) {
const [data, setData] = React.useState(null);

async function callBackend() {
const res = await window.__OPSKAT_EXT__.api.callTool("my-ext", "my_tool", { key: "value" });
setData(res);
}

return React.createElement("div", {}, /* UI */);
}
```

4. **Define `manifest.json`** with tools, actions, policies, and frontend pages.

5. **Build and test**:
```bash
cd extensions/my-ext && make build
go test -v ./backend/...
```

## Debugging

- **Logging**: Use `opskat.Log("info", "message")` — output is captured by the host.
- **Events**: In tests, use `th.Events()` to inspect all emitted action events.
- **Host functions**: Only available in WASM builds. Use `opskat.TestHost` for local testing.
- **Frontend**: Check `vite.config.ts` hostExternals plugin if imports fail — React and UI components come from `window.__OPSKAT_EXT__`.

---
Re-running `make build` and `opsctl ext dev` again hot-reloads the extension.

## License
## Releases

This project is open-sourced under the [GPLv3](./LICENSE) license.
Released artifacts and the extension index are handled by the extension store,
not by this repository.
Loading
Loading