瀏覽代碼

docs(cli): route external agents through interact command

Ma 7 月之前
父節點
當前提交
530bc89f4f
共有 5 個文件被更改,包括 88 次插入 和 4 次删除
  1. 15 1
      README.en.md
  2. 15 1
      README.md
  3. 29 0
      packages/cli/src/__tests__/interact-command.test.ts
  4. 8 1
      packages/cli/src/commands/interact.ts
  5. 21 1
      skills/SKILL.md

+ 15 - 1
README.en.md

@@ -42,7 +42,21 @@ clawhub install inkos          # Install from ClawHub
 
 
 If you installed via npm or cloned the repo, `skills/SKILL.md` is already included — 🦞 can read it directly without a separate ClawHub install.
 If you installed via npm or cloned the repo, `skills/SKILL.md` is already included — 🦞 can read it directly without a separate ClawHub install.
 
 
-Once installed, Claw can invoke InkOS atomic commands and control-surface operations (`plan chapter`/`compose chapter`/`draft`/`audit`/`revise`/`write next`) via `exec`, with `--json` output for structured decision-making. The recommended flow is: update `author_intent.md` or `current_focus.md`, run `plan` / `compose`, then decide whether to call `draft` or the full `write next` pipeline. You can also browse it on [ClawHub](https://clawhub.ai) by searching `inkos`.
+Once installed, Claw should prefer the shared interaction entry:
+
+```bash
+inkos interact --json --message "continue the current book, but keep the pacing tighter"
+```
+
+This routes through the same conversation executor used by the project TUI, so OpenClaw, TUI, and Studio stay on the same control brain. The JSON payload includes:
+- parsed request
+- assistant response text
+- updated interaction session
+- execution state
+- pending decision
+- recent events
+
+Atomic commands (`plan chapter` / `compose chapter` / `draft` / `audit` / `revise` / `write next`) are still available, but they are now lower-level tools rather than the preferred OpenClaw entry. You can also browse it on [ClawHub](https://clawhub.ai) by searching `inkos`.
 
 
 ### Configure
 ### Configure
 
 

+ 15 - 1
README.md

@@ -51,7 +51,21 @@ clawhub install inkos          # 从 ClawHub 安装 InkOS Skill
 
 
 通过 npm 安装或克隆本项目时,`skills/SKILL.md` 已包含在内,🦞 可直接读取——无需额外从 ClawHub 安装。
 通过 npm 安装或克隆本项目时,`skills/SKILL.md` 已包含在内,🦞 可直接读取——无需额外从 ClawHub 安装。
 
 
-安装后,Claw 可通过 `exec` 调用 InkOS 的原子命令和控制面操作(`plan chapter`/`compose chapter`/`draft`/`audit`/`revise`/`write next`),`--json` 输出结构化数据供 Claw 解析决策。推荐流程是先更新 `author_intent.md` 或 `current_focus.md`,再 `plan` / `compose`,最后决定是否 `draft` 或完整 `write next`。也可以在 [ClawHub](https://clawhub.ai) 搜索 `inkos` 在线查看。
+安装后,Claw 应优先通过共享交互入口调用 InkOS:
+
+```bash
+inkos interact --json --message "继续当前书,但把节奏再收紧一点"
+```
+
+这条入口直接走和项目 TUI 相同的交互执行内核,因此 OpenClaw、TUI、Studio 共用同一套控制脑。返回的 JSON 包含:
+- 解析后的 request
+- assistant 文本回复
+- 更新后的 interaction session
+- execution state
+- pending decision
+- recent events
+
+`plan chapter` / `compose chapter` / `draft` / `audit` / `revise` / `write next` 这些原子命令仍然保留,但更适合作为底层工具,而不是 OpenClaw 的首选入口。也可以在 [ClawHub](https://clawhub.ai) 搜索 `inkos` 在线查看。
 
 
 ### 配置
 ### 配置
 
 

+ 29 - 0
packages/cli/src/__tests__/interact-command.test.ts

@@ -85,6 +85,35 @@ describe("interact command", () => {
     expect(parsed.session.automationMode).toBe("auto");
     expect(parsed.session.automationMode).toBe("auto");
   });
   });
 
 
+  it("accepts --message as an explicit OpenClaw-friendly input channel", async () => {
+    const runInteraction = vi.fn(async () => ({
+      request: { intent: "continue_book" },
+      responseText: "Continuing via --message.",
+      session: {
+        activeBookId: "harbor",
+        automationMode: "semi",
+        messages: [],
+        events: [],
+      },
+    }));
+
+    const program = createProgram({
+      runInteraction,
+      readInteractionInput: async () => "",
+    });
+
+    await program.parseAsync(["interact", "--book", "harbor", "--message", "continue current book"], {
+      from: "user",
+    });
+
+    expect(runInteraction).toHaveBeenCalledWith(
+      expect.objectContaining({
+        input: "continue current book",
+        activeBookId: "harbor",
+      }),
+    );
+  });
+
   it("reads the message from stdin when no args are provided", async () => {
   it("reads the message from stdin when no args are provided", async () => {
     const runInteraction = vi.fn(async () => ({
     const runInteraction = vi.fn(async () => ({
       request: { intent: "explain_status" },
       request: { intent: "explain_status" },

+ 8 - 1
packages/cli/src/commands/interact.ts

@@ -29,8 +29,14 @@ export interface InteractCommandHooks {
 
 
 async function readInteractionInput(
 async function readInteractionInput(
   args: ReadonlyArray<string>,
   args: ReadonlyArray<string>,
+  explicitMessage: string | undefined,
   readInput?: () => Promise<string>,
   readInput?: () => Promise<string>,
 ): Promise<string> {
 ): Promise<string> {
+  const explicit = explicitMessage?.trim();
+  if (explicit) {
+    return explicit;
+  }
+
   const inline = args.join(" ").trim();
   const inline = args.join(" ").trim();
   if (inline) {
   if (inline) {
     return inline;
     return inline;
@@ -61,10 +67,11 @@ export function createInteractCommand(hooks: InteractCommandHooks = {}): Command
   return new Command("interact")
   return new Command("interact")
     .description("Run a shared natural-language interaction against the current project")
     .description("Run a shared natural-language interaction against the current project")
     .argument("[message...]", "Natural-language message")
     .argument("[message...]", "Natural-language message")
+    .option("--message <text>", "Explicit natural-language message")
     .option("--book <bookId>", "Bind a specific active book for this interaction")
     .option("--book <bookId>", "Bind a specific active book for this interaction")
     .option("--json", "Emit structured JSON for external agents")
     .option("--json", "Emit structured JSON for external agents")
     .action(async (messageArgs: ReadonlyArray<string>, opts) => {
     .action(async (messageArgs: ReadonlyArray<string>, opts) => {
-      const input = await readInteractionInput(messageArgs, hooks.readInput);
+      const input = await readInteractionInput(messageArgs, opts.message, hooks.readInput);
       const projectRoot = process.cwd();
       const projectRoot = process.cwd();
       const tools = hooks.createTools
       const tools = hooks.createTools
         ? await hooks.createTools(projectRoot)
         ? await hooks.createTools(projectRoot)

+ 21 - 1
skills/SKILL.md

@@ -112,7 +112,27 @@ inkos status
    inkos review approve-all
    inkos review approve-all
    ```
    ```
 
 
-### Workflow 2.5: Steering Chapter Focus Before Writing
+### Workflow 2.5: Shared Natural-Language Control (Recommended For OpenClaw)
+
+When InkOS is being driven by OpenClaw or another external agent, prefer the shared interaction executor instead of stitching together many ad-hoc CLI calls:
+
+```bash
+inkos interact --json --message "continue the current book, but keep the pacing tighter"
+inkos interact --json --message "rewrite chapter 3"
+inkos interact --json --book my-book --message "switch to auto mode"
+```
+
+This returns a structured payload containing:
+- the routed request
+- assistant response text
+- updated interaction session
+- execution state
+- pending decision
+- recent interaction events
+
+Use this as the primary OpenClaw entry because it shares the same control layer as the project TUI.
+
+### Workflow 2.6: Steering Chapter Focus Before Writing
 
 
 Use this when the user says things like "pull focus back to the mentor conflict", "pause the merchant guild subplot", or "change what the next chapter should prioritize".
 Use this when the user says things like "pull focus back to the mentor conflict", "pause the merchant guild subplot", or "change what the next chapter should prioritize".