Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 66 additions & 1 deletion contrib/skills/shared/oo/references/connector-execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,64 @@ Facts:
- The schema returned by `oo connector schema` is the public contract used to
build payloads and inspect the action result shape.

## Proxy a provider API request

Use `oo connector proxy` only when the selected connector service supports
proxy execution and no purpose-built connector action is available for the
user's requested provider endpoint. Do not use proxy as a first choice when a
matching connector action exists.

Canonical forms:

```bash
oo connector proxy "<serviceName>" \
--endpoint "<provider-endpoint-path>" \
--method GET \
--query '<json object>' \
--json
```

```bash
oo connector proxy "<serviceName>" \
--data '{"endpoint":"/path","method":"POST","body":{}}' \
--json
```

Facts:

- `serviceName` is the only positional argument.
- `--data` accepts the full proxy request object:
`{ "endpoint": string, "method": "GET" | "POST" | "PUT" | "PATCH" | "DELETE", "query"?: object, "headers"?: object, "body"?: unknown }`.
- Without `--data`, build the same object with `--endpoint`, `--method`, and
optional `--query`, `--headers`, and `--body`.
- `--query`, `--headers`, and `--body` are parsed as JSON. To send text in
`body`, pass a JSON string such as `"hello"`.
- Do not pass provider credentials, `Authorization`, cookies, or API keys in
proxy headers. The connector service injects authentication from the
connected app.
- Use `--app-id "<id>"` or `--alias "<alias>"` only when the user identified a
specific connected app. They cannot be combined.
- JSON output has this stable shape:

```json
{
"data": {
"status": 200,
"headers": {},
"data": {}
},
"meta": {
"executionId": "execution-id",
"service": "serviceName",
"appId": "optional-app-id"
}
}
```

## Choose the run identity

A connector action runs under one identity. Pick it from what the user said:
A connector action or proxy request runs under one identity. Pick it from what
the user said:

- If the user does not mention any organization, run under their personal
identity: add nothing extra. This is the default.
Expand All @@ -113,6 +168,16 @@ oo connector run "<serviceName>" \
--json
```

For proxy requests, use the same identity option:

```bash
oo connector proxy "<serviceName>" \
--endpoint "<provider-endpoint-path>" \
--method GET \
--organization "<organizationName>" \
--json
```

- If the user has a configured default organization but explicitly asks for this
one run to be personal, add `--personal`.

Expand Down
47 changes: 45 additions & 2 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,9 @@ Persist one configuration value.
pending telemetry events immediately and the current `config set` invocation is
not recorded as telemetry.
- Value rules: for `identity.organization`, use any non-empty organization name.
It sets the default organization identity used by `oo connector run` when
neither `--organization` nor `--personal` is passed.
It sets the default organization identity used by `oo connector run` and
`oo connector proxy` when neither `--organization` nor `--personal` is
passed.

### `oo config unset <key>`

Expand Down Expand Up @@ -608,6 +609,48 @@ Validate input data and run one connector action.
- Notes: while waiting for an async result action in text mode, interactive
terminals show progress on stderr. JSON output does not include progress text.

### `oo connector proxy <serviceName>`

Proxy a provider API request through a connected connector app.

- Arguments: `<serviceName>` is the service name.
- Options: `-d, --data <data>` accepts a complete proxy request JSON object or
Comment thread
hyrious marked this conversation as resolved.
`@path` to a JSON file. The object shape is
`{ endpoint, method, query?, headers?, body? }`.
- Options: `--input <data>` is an alias for `--data <data>`.
- Options: without `--data`, use `--endpoint <endpoint>` and
`--method <method>` plus optional `--query <json>`, `--headers <json>`, and
`--body <json>` to build the same request object. The `--data` form cannot
be combined with these split request options.
- Options: `--endpoint` is a provider endpoint path relative to the provider
proxy base URL, or an allowed absolute HTTPS URL.
- Options: `--method` must be one of `GET`, `POST`, `PUT`, `PATCH`, or
`DELETE`. Values are case-insensitive.
- Options: `--query` must be a JSON object whose values are strings, numbers,
booleans, or `null`.
- Options: `--headers` must be a JSON object with string values.
Authentication headers are injected by the connector service from the
connected app; callers should not pass provider credentials through CLI
options.
- Options: `--body` is parsed as JSON. To send a text body, pass a JSON string
such as `"hello"`.
- Options: `--organization <name>` runs the proxy request under the given
organization identity instead of your personal identity. `--org <name>` is an
alias for `--organization <name>`. When omitted, the request runs under the
`identity.organization` config default if set, otherwise your personal
identity.
- Options: `--personal` runs the proxy request under your personal identity and
ignores any configured default organization. It cannot be combined with
`--organization`.
- Options: `--format=json` and `--json` print a JSON object.
- Output: JSON output keeps the stable shape
`{ data: { status, headers, data }, meta: { executionId, service } }`.
- Errors: stderr prints the connector proxy HTTP status and includes the server
`message` and `errorCode` when the failure response provides them.
- Notes: `oo connector proxy` does not use connector action schemas or schema
cache. Use it when the selected connector supports proxy execution and no
purpose-built connector action is available.

## Search

### `oo search <text>`
Expand Down
39 changes: 38 additions & 1 deletion docs/commands.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@
CLI 还会立即尝试清空待发送 telemetry 事件,并且本次 `config set` 调用自身不会被记录为
telemetry。
- 取值规则:当 `<key>` 为 `identity.organization` 时,支持任意非空的组织名称。
它设置 `oo connector run` 在未传 `--organization` 或 `--personal` 时使用的默认组织身份。
它设置 `oo connector run` 和 `oo connector proxy` 在未传 `--organization` 或
`--personal` 时使用的默认组织身份。

### `oo config unset <key>`

Expand Down Expand Up @@ -522,6 +523,42 @@ CLI 默认记录受隐私约束的命令使用 telemetry。事件不包含 free-
- 说明:text 模式下等待 async result action 时,交互式终端会在 stderr
显示进度。JSON 输出不会混入进度文本。

### `oo connector proxy <serviceName>`

通过已连接的 connector app 代理 provider API 请求。

- 参数:`<serviceName>` 为服务名。
- 选项:`-d, --data <data>` 接收完整 proxy request JSON object,或使用
`@路径` 读取 JSON 文件。对象形状为
`{ endpoint, method, query?, headers?, body? }`。
- 选项:`--input <data>` 是 `--data <data>` 的 alias。
- 选项:未传 `--data` 时,使用 `--endpoint <endpoint>` 和
`--method <method>`,以及可选的 `--query <json>`、`--headers <json>`、
`--body <json>` 组装同样的 request object。`--data` 形式不能与这些拆分
request 选项同时使用。
- 选项:`--endpoint` 是相对于 provider proxy base URL 的 provider endpoint
path,或允许的绝对 HTTPS URL。
- 选项:`--method` 必须是 `GET`、`POST`、`PUT`、`PATCH` 或 `DELETE`,大小写不敏感。
- 选项:`--query` 必须是 JSON object,值只能是 string、number、boolean 或
`null`。
- 选项:`--headers` 必须是 string 值的 JSON object。认证 header 会由
connector service 根据已连接 app 注入;调用方不应通过 CLI 选项传 provider
credential。
- 选项:`--body` 会按 JSON 解析。如需发送文本 body,请传 JSON string,例如
`"hello"`。
- 选项:`--organization <name>` 以指定组织身份运行该 proxy 请求,而非个人身份。
`--org <name>` 是 `--organization <name>` 的 alias。省略时,若配置了
`identity.organization` 默认值则使用该组织,否则使用个人身份。
- 选项:`--personal` 以个人身份运行该 proxy 请求,并忽略已配置的默认组织。
不能与 `--organization` 同时使用。
- 选项:`--format=json` 和 `--json` 会输出 JSON 对象。
- 输出:JSON 输出保持稳定结构
`{ data: { status, headers, data }, meta: { executionId, service } }`。
- 错误:stderr 会打印 connector proxy HTTP 状态;如果失败响应提供了
`message` 和 `errorCode`,也会一并包含。
- 说明:`oo connector proxy` 不使用 connector action schema 或 schema cache。
当选中的 connector 支持 proxy execution 且没有专用 connector action 时使用。

## Search

### `oo search <text>`
Expand Down
23 changes: 0 additions & 23 deletions src/application/commands/connector/identity.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { describe, expect, test } from "bun:test";

import {
applyConnectorIdentityToUrl,
connectorIdentityHeaders,
resolveConnectorIdentity,
} from "./identity.ts";
Expand Down Expand Up @@ -63,28 +62,6 @@ describe("resolveConnectorIdentity", () => {
});
});

describe("applyConnectorIdentityToUrl", () => {
test("adds the organization query parameter for an organization identity", () => {
const url = new URL("https://connector.oomol.com/v1/actions/gmail.send_mail");

applyConnectorIdentityToUrl(url, { organization: "acme" });

expect(url.toString()).toBe(
"https://connector.oomol.com/v1/actions/gmail.send_mail?organization=acme",
);
});

test("leaves the URL untouched for the personal identity", () => {
const url = new URL("https://connector.oomol.com/v1/actions/gmail.send_mail");

applyConnectorIdentityToUrl(url, {});

expect(url.toString()).toBe(
"https://connector.oomol.com/v1/actions/gmail.send_mail",
);
});
});

describe("connectorIdentityHeaders", () => {
test("returns the organization header for an organization identity", () => {
expect(connectorIdentityHeaders({ organization: "acme" })).toEqual({
Expand Down
17 changes: 3 additions & 14 deletions src/application/commands/connector/identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
// personal => {} (no organization)
// org => { organization }
//
// The identity is resolved once per `connector run` invocation and then applied
// only to the action run requests (POST /v1/actions/...). The action schema /
// metadata layer is identity-independent and is intentionally left untouched.
// The identity is resolved once per connector invocation and then applied only
// to execution requests. The action schema / metadata layer is
// identity-independent and is intentionally left untouched.
//
// This struct is the extension point for additional identity dimensions: a new
// field here plus a branch in the request helpers below is all a future
Expand Down Expand Up @@ -53,17 +53,6 @@ export function resolveConnectorIdentity(input: {
return { identity: {}, source: "personal" };
}

// Adds the identity query parameters to a connector action request URL. This is
// the single place that maps identity fields to query parameters.
export function applyConnectorIdentityToUrl(
url: URL,
identity: ConnectorIdentity | undefined,
): void {
if (identity?.organization !== undefined) {
url.searchParams.set("organization", identity.organization);
}
}

// Builds the identity request headers (`x-oo-organization`). Returns an empty
// object for the personal identity so callers can spread it unconditionally.
export function connectorIdentityHeaders(
Expand Down
Loading