🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@shadowob/connector

Package Overview
Dependencies
Maintainers
1
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shadowob/connector - npm Package Compare versions

Comparing version
1.1.63
to
1.1.64
+2
-2
package.json
{
"name": "@shadowob/connector",
"version": "1.1.63",
"version": "1.1.64",
"description": "Shadow connector helpers for OpenClaw, Hermes Agent, and cc-connect",

@@ -75,3 +75,3 @@ "type": "module",

"yaml": "^2.8.4",
"@shadowob/shared": "1.1.63"
"@shadowob/shared": "1.1.64"
},

@@ -78,0 +78,0 @@ "scripts": {

@@ -180,3 +180,3 @@ import { serve } from '@hono/node-server'

app.post('/api/shadow/commands/tickets.list', async (c) => {
app.post('/.shadow/commands/tickets.list', async (c) => {
const parsed = await readOAuthEnvelope<Record<string, never>>(c, 'tickets.list')

@@ -193,3 +193,3 @@ if (!parsed.ok) return parsed.response

app.post('/api/shadow/commands/tickets.create', async (c) => {
app.post('/.shadow/commands/tickets.create', async (c) => {
const parsed = await readOAuthEnvelope<unknown>(c, 'tickets.create')

@@ -206,3 +206,3 @@ if (!parsed.ok) return parsed.response

app.post('/api/shadow/commands/tickets.update_status', async (c) => {
app.post('/.shadow/commands/tickets.update_status', async (c) => {
const parsed = await readOAuthEnvelope<unknown>(c, 'tickets.update_status')

@@ -218,3 +218,3 @@ if (!parsed.ok) return parsed.response

app.post('/api/shadow/commands/files.summarize_upload', async (c) => {
app.post('/.shadow/commands/files.summarize_upload', async (c) => {
const auth = await authenticateShadowCommand(c, 'files.summarize_upload')

@@ -221,0 +221,0 @@ if (!auth.ok) return auth.response

@@ -35,7 +35,7 @@ # Scaffold

- `shadow-app.local.json` with `shadow.app/1`, an OAuth bearer API, iframe entry, icon route, and one neutral `status.get` command.
- `shadow-app.local.json` with `shadow.app/1`, an App-owned API base URL, iframe entry, icon route, and one neutral `status.get` command whose ingress is `/.shadow/commands/status.get`.
- `src/shadow-app.generated.ts`, generated from the manifest so command input types are inferred from JSON Schema.
- `src/manifest.ts`, using `defineShadowServerApp`.
- `src/commands.ts`, using `shadowApp.defineCommands` for domain command handlers.
- `src/server.ts`, using `shadowApp.executeCommand` for server-origin commands and launch-token runtime routes for iframe commands/inbox lookup, while exporting an import-safe Hono app.
- `src/server.ts`, exporting an import-safe Hono app with App-owned `/api/*` routes and Shadow gateway ingress under `/.shadow/*`.
- `src/data.ts`, using `createShadowServerAppJsonStore`.

@@ -53,3 +53,3 @@ - `src/ui.ts`, a minimal iframe shell that should be replaced with the user's App experience.

4. Implement domain data and commands.
5. Replace the iframe shell with the real App UI.
5. Replace the iframe shell with the real App UI. The UI must call App-owned `/api/*`, not command ingress routes.
6. Run local preview through `shadowob app preview --manifest-file`.

@@ -65,2 +65,3 @@ 7. For Cloud runtime publish, keep the project under `$SHADOWOB_WORKSPACE`, `/workspace`, or `/home/shadow`, then run `PORT=<port> pnpm start:background` and verify `/health` with `curl`.

- Keep generated files small; add abstractions only after the user's App needs them.
- Keep platform ingress outside App-owned `/api/*`.
- Keep the Dockerfile non-root and production-only; do not add runtime docs bundles or app-specific patches to the image.

@@ -7,5 +7,7 @@ # App Standard

- Shadow server is the control plane: installation, authorization, OAuth, Buddy grants, command policy, audit, and entry routing.
- The App backend is the data plane: business logic, iframe launch handling, command execution, event streaming, and App-owned state.
- Buddies operate Apps through the Shadow App protocol and the `shadowob app` CLI. Do not expose backend routes, App tokens, shared secrets, or container ports to Buddies.
- Shadow server is the control plane: installation, authorization, Buddy grants, command policy, approvals, audit, and gateway routing.
- The App backend is the data plane: business logic, App-owned API, App users, App sessions, command handlers, and App-owned state.
- App UI calls only App-owned `/api/*`.
- Shadow platform ingress in the App lives only under `/.shadow/*`.
- Buddies and CLI operate Apps through `shadowob app discover`, `shadowob app skills`, and `shadowob app call`. Do not expose backend routes, App tokens, shared secrets, or container ports to Buddies.
- Agents may develop and run Apps, but publishing, domain mounting, grants, and backups must go through the Shadow CLI or Cloud control plane.

@@ -47,7 +49,39 @@

- Set `iframe.entry` to the user-facing entry URL and `iframe.allowedOrigins` to exact origins.
- Set `api.baseUrl` to the App backend HTTPS base URL.
- Use `api.auth.type: "oauth2-bearer"`.
- Keep commands small and stable. Each command must declare JSON Schema, `permission`, `action`, `dataClass`, and approval behavior when applicable.
- Set `api.baseUrl` to the App backend HTTPS origin. This is the App origin, not a Shadow protocol namespace.
- Keep commands small and stable. Each command must declare `ingress.path`, `ingress.auth`, JSON Schema, `permission`, `action`, `dataClass`, and approval behavior when applicable.
- Command ingress paths must live under `/.shadow/commands/*`.
- Keep manifest `skills` short and actionable. Do not put full API documentation in the manifest.
Example command entry:
```json
{
"name": "tickets.create",
"ingress": {
"path": "/.shadow/commands/tickets.create",
"auth": "shadow-command-jwt"
},
"permission": "ticket_desk.tickets:write",
"action": "write",
"dataClass": "server-private",
"inputSchema": {
"type": "object",
"properties": {
"title": { "type": "string", "minLength": 1 }
},
"required": ["title"],
"additionalProperties": false
}
}
```
## API Rules
- `/api/*` is App-owned. Use it for browser UI and synchronous business operations.
- `/.shadow/commands/*` is Shadow gateway ingress. It accepts only Shadow-signed command requests.
- `/.shadow/backup/*` and `/.shadow/restore/*` are platform lifecycle ingress when the App supports backup/restore hooks.
- Keep platform ingress outside App-owned `/api/*`.
- Do not read manifest command ingress paths from browser code.
- Treat `avatarUrl` fields in Shadow identity snapshots as stable public image URLs. Render user avatars, server icons, and Buddy avatars directly; private media delivery is for attachments and workspace files.
## SDK And Protocol

@@ -59,6 +93,6 @@

- `shadow-server-app typegen` to generate typed command input from the manifest.
- `shadowApp.defineCommands`, `shadowApp.executeCommand`, `shadowApp.executeLocal`, and `shadowApp.error` for command protocol handling.
- `shadowApp.defineCommands` and the Shadow command ingress helpers for command handling.
- `createShadowServerAppJsonStore` for environment-configured JSON persistence.
Do not hand-roll Bearer token parsing, token introspection, manifest rewriting, command JSON Schema validation, actor display labels, or command error envelopes.
Do not hand-roll manifest rewriting, Shadow command token validation, command JSON Schema validation, actor display labels, or command error envelopes.

@@ -68,3 +102,4 @@ ## Authorization

- Treat authentication and authorization as separate concerns.
- OAuth or PAT scope is not enough. A command must also satisfy App grant, server access, command permission, resource rule, and action policy.
- App UI authentication is App-owned: App session, App OAuth account link, or explicit anonymous policy.
- Shadow OAuth or PAT scope is not enough for command execution. Shadow gateway must also satisfy server access, command permission, resource rule, action policy, approval, and Buddy grant.
- Use `server-private` or `channel-private` for ordinary server data.

@@ -76,4 +111,3 @@ - Do not use `financial`, `secret`, or `cloud-secret` unless the Shadow server policy explicitly supports the use case.

- Keep iframe launch URLs stable; avoid query strings that force remounts on every launch refresh.
- Cache launch context until close to expiry.
- Keep iframe URLs stable.
- Keep global navigation data warm while refetching.

@@ -93,3 +127,3 @@ - Prefer event streams or App-local patches over iframe remounts.

Call a command:
Call a command through Shadow gateway:

@@ -104,3 +138,3 @@ ```bash

Attach binary input through the command protocol only:
Attach binary input through Shadow gateway only:

@@ -114,1 +148,3 @@ ```bash

```
Never call App `/.shadow/*` directly from Buddy or CLI.

@@ -20,3 +20,4 @@ ---

- Use the modeled `@shadowob/sdk` App runtime instead of reimplementing manifest rewriting, Bearer token extraction, token introspection, command request parsing, JSON Schema validation, or actor labels.
- Keep App-owned `/api/*` separate from Shadow gateway ingress. New Apps must expose Shadow platform routes only under `/.shadow/*`.
- Use the modeled `@shadowob/sdk` App helpers instead of reimplementing manifest rewriting, Shadow command token validation, command request parsing, JSON Schema validation, or actor labels.
- Use `shadow.app/1` manifests, stable `appKey` values, stable command names, and explicit `permission`, `action`, and `dataClass` on every command.

@@ -27,3 +28,3 @@ - Buddies must operate installed Apps through `shadowob app discover`, `shadowob app skills`, and `shadowob app call`; never hand a Buddy raw HTTP routes, app tokens, or shared secrets.

- Never load Shadow OAuth inside the App iframe. Use a top-level popup or navigation and include `allow-popups-to-escape-sandbox` on the iframe sandbox.
- Keep iframe launch URLs stable. Cache launch context until near expiry, keep global navigation data warm while refetching, and prefer event streams or app-local patches over iframe remounts.
- Keep iframe URLs stable. App UI must call App-owned `/api/*`; it must not call command ingress routes or Shadow gateway routes directly.
- Declare state paths and backup policy before publishing an agent-hosted app. Runtime code, build output, config, secrets, and mutable app state must have separate ownership and lifecycle.

@@ -30,0 +31,0 @@ - For a new App, start from `shadowob app generate <app-key>` or `node scripts/create-server-app.mjs <app-key>` unless the user asks for a different stack.

import { RuntimeSessionState, RuntimeSessionPetReaction, RuntimeSessionPetActivity } from '@shadowob/shared/types';
export { RuntimeSessionPetActivity, RuntimeSessionPetReaction, RuntimeSessionState, runtimeSessionPetReactionForState } from '@shadowob/shared/types';
type ConnectorRuntimeId = 'openclaw' | 'hermes' | 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'kimi' | 'copilot' | 'antigravity';
type RuntimeInstanceStatus = 'running' | 'available' | 'stopped' | 'missing' | 'error';
interface RuntimeInstanceInfo {
runtimeId: ConnectorRuntimeId;
instanceId: string;
label: string;
status: RuntimeInstanceStatus;
endpoint?: string | null;
capabilities: string[];
error?: string | null;
metadata?: Record<string, unknown>;
}
interface RuntimeSessionInfo {
runtimeId: ConnectorRuntimeId;
instanceId: string;
sessionId: string;
title?: string | null;
workDir?: string | null;
state: RuntimeSessionState;
petReaction: RuntimeSessionPetReaction;
petActivity?: RuntimeSessionPetActivity;
model?: string | null;
lastActivityAt?: string | null;
startedAt?: string | null;
source: 'server' | 'cli' | 'database' | 'storage' | 'transcript';
native?: Record<string, unknown>;
}
interface RuntimeSessionSnapshot {
scannedAt: string;
runtimeIds: ConnectorRuntimeId[];
instances: RuntimeInstanceInfo[];
sessions: RuntimeSessionInfo[];
}
type RuntimeSessionEventType = 'snapshot' | 'session_added' | 'session_removed' | 'session_changed';
interface RuntimeSessionEvent {
type: RuntimeSessionEventType;
at: string;
runtimeId?: ConnectorRuntimeId;
sessionId?: string;
previousState?: RuntimeSessionState;
state?: RuntimeSessionState;
previousPetReaction?: RuntimeSessionPetReaction;
petReaction?: RuntimeSessionPetReaction;
previousPetActivity?: RuntimeSessionPetActivity;
petActivity?: RuntimeSessionPetActivity;
session?: RuntimeSessionInfo;
snapshot?: RuntimeSessionSnapshot;
}
interface RuntimeSessionScanOptions {
runtimeId?: string;
opencodeUrl?: string;
homeDir?: string;
env?: NodeJS.ProcessEnv;
limit?: number;
}
interface RuntimeSessionSendOptions extends RuntimeSessionScanOptions {
runtimeId: string;
sessionId: string;
message: string;
timeoutMs?: number;
}
interface RuntimeSessionSendResult {
runtimeId: ConnectorRuntimeId;
sessionId: string;
accepted: boolean;
mode: 'server' | 'process';
events?: unknown[];
stdout?: string;
stderr?: string;
exitCode?: number | null;
}
declare function runtimeSessionPetReaction(session: Pick<RuntimeSessionInfo, 'state'> & {
petReaction?: RuntimeSessionPetReaction;
}): RuntimeSessionPetReaction;
declare function scanRuntimeSessions(options?: RuntimeSessionScanOptions): Promise<RuntimeSessionSnapshot>;
declare function diffRuntimeSessionSnapshots(previous: RuntimeSessionSnapshot | null, next: RuntimeSessionSnapshot): RuntimeSessionEvent[];
declare function renderRuntimeSessionPanel(snapshot: RuntimeSessionSnapshot): string;
declare function sendRuntimeSessionMessage(options: RuntimeSessionSendOptions): Promise<RuntimeSessionSendResult>;
export { type RuntimeInstanceInfo, type RuntimeInstanceStatus, type RuntimeSessionEvent, type RuntimeSessionEventType, type RuntimeSessionInfo, type RuntimeSessionScanOptions, type RuntimeSessionSendOptions, type RuntimeSessionSendResult, type RuntimeSessionSnapshot, diffRuntimeSessionSnapshots, renderRuntimeSessionPanel, runtimeSessionPetReaction, scanRuntimeSessions, sendRuntimeSessionMessage };
import { RuntimeSessionState, RuntimeSessionPetReaction, RuntimeSessionPetActivity } from '@shadowob/shared/types';
export { RuntimeSessionPetActivity, RuntimeSessionPetReaction, RuntimeSessionState, runtimeSessionPetReactionForState } from '@shadowob/shared/types';
type ConnectorRuntimeId = 'openclaw' | 'hermes' | 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'kimi' | 'copilot' | 'antigravity';
type RuntimeInstanceStatus = 'running' | 'available' | 'stopped' | 'missing' | 'error';
interface RuntimeInstanceInfo {
runtimeId: ConnectorRuntimeId;
instanceId: string;
label: string;
status: RuntimeInstanceStatus;
endpoint?: string | null;
capabilities: string[];
error?: string | null;
metadata?: Record<string, unknown>;
}
interface RuntimeSessionInfo {
runtimeId: ConnectorRuntimeId;
instanceId: string;
sessionId: string;
title?: string | null;
workDir?: string | null;
state: RuntimeSessionState;
petReaction: RuntimeSessionPetReaction;
petActivity?: RuntimeSessionPetActivity;
model?: string | null;
lastActivityAt?: string | null;
startedAt?: string | null;
source: 'server' | 'cli' | 'database' | 'storage' | 'transcript';
native?: Record<string, unknown>;
}
interface RuntimeSessionSnapshot {
scannedAt: string;
runtimeIds: ConnectorRuntimeId[];
instances: RuntimeInstanceInfo[];
sessions: RuntimeSessionInfo[];
}
type RuntimeSessionEventType = 'snapshot' | 'session_added' | 'session_removed' | 'session_changed';
interface RuntimeSessionEvent {
type: RuntimeSessionEventType;
at: string;
runtimeId?: ConnectorRuntimeId;
sessionId?: string;
previousState?: RuntimeSessionState;
state?: RuntimeSessionState;
previousPetReaction?: RuntimeSessionPetReaction;
petReaction?: RuntimeSessionPetReaction;
previousPetActivity?: RuntimeSessionPetActivity;
petActivity?: RuntimeSessionPetActivity;
session?: RuntimeSessionInfo;
snapshot?: RuntimeSessionSnapshot;
}
interface RuntimeSessionScanOptions {
runtimeId?: string;
opencodeUrl?: string;
homeDir?: string;
env?: NodeJS.ProcessEnv;
limit?: number;
}
interface RuntimeSessionSendOptions extends RuntimeSessionScanOptions {
runtimeId: string;
sessionId: string;
message: string;
timeoutMs?: number;
}
interface RuntimeSessionSendResult {
runtimeId: ConnectorRuntimeId;
sessionId: string;
accepted: boolean;
mode: 'server' | 'process';
events?: unknown[];
stdout?: string;
stderr?: string;
exitCode?: number | null;
}
declare function runtimeSessionPetReaction(session: Pick<RuntimeSessionInfo, 'state'> & {
petReaction?: RuntimeSessionPetReaction;
}): RuntimeSessionPetReaction;
declare function scanRuntimeSessions(options?: RuntimeSessionScanOptions): Promise<RuntimeSessionSnapshot>;
declare function diffRuntimeSessionSnapshots(previous: RuntimeSessionSnapshot | null, next: RuntimeSessionSnapshot): RuntimeSessionEvent[];
declare function renderRuntimeSessionPanel(snapshot: RuntimeSessionSnapshot): string;
declare function sendRuntimeSessionMessage(options: RuntimeSessionSendOptions): Promise<RuntimeSessionSendResult>;
export { type RuntimeInstanceInfo, type RuntimeInstanceStatus, type RuntimeSessionEvent, type RuntimeSessionEventType, type RuntimeSessionInfo, type RuntimeSessionScanOptions, type RuntimeSessionSendOptions, type RuntimeSessionSendResult, type RuntimeSessionSnapshot, diffRuntimeSessionSnapshots, renderRuntimeSessionPanel, runtimeSessionPetReaction, scanRuntimeSessions, sendRuntimeSessionMessage };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display