u1s1-cli 0.16.5 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,6 +58,11 @@ export declare function toProviderModels(models: ModelDef[]): {
58
58
  * 这是 pi 自带 llama provider 的同款兜底,本地服务会忽略 Authorization 头。
59
59
  */
60
60
  export declare function endpointProviderEntry(ep: CustomEndpoint): Record<string, unknown>;
61
+ /**
62
+ * 生成 /workflow 提示词模板到 <agentDir>/prompts/workflow.md:引导主 agent
63
+ * 拆解任务 → 生成沙箱脚本 → 调 run_workflow 执行。每次启动重写,便于随版迭代文案。
64
+ */
65
+ export declare function ensureWorkflowPromptTemplate(): void;
61
66
  export declare function scrubForeignProviderEnv(): void;
62
67
  /** 把各端点密钥放进环境(TUI 直接 process.env;web 传给子进程)。 */
63
68
  export declare function endpointKeyEnv(): Record<string, string>;
@@ -139,6 +139,19 @@ export function writeWebToolsExtension(cfg, features) {
139
139
  const imageLine = features.imageGen
140
140
  ? ` pi.registerTool(tools.createImageTool({ baseUrl: ${JSON.stringify(cfg.baseUrl)}, apiKey: process.env.U1S1_API_KEY }));\n`
141
141
  : "";
142
+ // spawn_subagent / run_workflow 只给主会话注册;子 agent 环境里跳过,杜绝孙 agent 递归 spawn
143
+ const subagentBlock = ` if (process.env.U1S1_IN_SUBAGENT !== "1") {\n` +
144
+ ` let getParentModel = () => undefined;\n` +
145
+ ` pi.on("session_start", (_event, ctx) => {\n` +
146
+ ` const m = ctx.model;\n` +
147
+ ` if (m && typeof m.provider === "string" && typeof m.id === "string") {\n` +
148
+ ` getParentModel = () => ({ provider: m.provider, id: m.id });\n` +
149
+ ` }\n` +
150
+ ` });\n` +
151
+ ` pi.registerTool(tools.createSubagentTool(getParentModel));\n` +
152
+ ` const workflow = await import(${JSON.stringify(new URL("./workflow/tool.js", import.meta.url).href)});\n` +
153
+ ` pi.registerTool(workflow.createRunWorkflowTool(getParentModel));\n` +
154
+ ` }\n`;
142
155
  writeFileSync(join(dir, "u1s1-tools.js"), `// 由 u1s1 每次启动自动生成,请勿手改\n` +
143
156
  `export default async function (pi) {\n` +
144
157
  ` if (process.env.U1S1_TOOLS_VIA_EXTENSION !== "1") return;\n` +
@@ -146,6 +159,7 @@ export function writeWebToolsExtension(cfg, features) {
146
159
  searchLine +
147
160
  ` pi.registerTool(tools.createFetchTool({ baseUrl: ${JSON.stringify(cfg.baseUrl)}, apiKey: process.env.U1S1_API_KEY, renderFallback: ${features.webFetchRender} }));\n` +
148
161
  imageLine +
162
+ subagentBlock +
149
163
  `}\n`);
150
164
  }
151
165
  /**
@@ -297,6 +311,39 @@ export function endpointProviderEntry(ep) {
297
311
  models: toProviderModels(ep.models),
298
312
  };
299
313
  }
314
+ /**
315
+ * 生成 /workflow 提示词模板到 <agentDir>/prompts/workflow.md:引导主 agent
316
+ * 拆解任务 → 生成沙箱脚本 → 调 run_workflow 执行。每次启动重写,便于随版迭代文案。
317
+ */
318
+ export function ensureWorkflowPromptTemplate() {
319
+ const dir = join(agentDir, "prompts");
320
+ mkdirSync(dir, { recursive: true });
321
+ const content = `---
322
+ description: Orchestrate many sub-agents for a large parallelizable task via run_workflow
323
+ argument-hint: "<task description>"
324
+ ---
325
+ # Workflow: $ARGUMENTS
326
+
327
+ First decide whether this task really needs a workflow. Good fit: many independent pieces (e.g. translating each locale file, renaming across hundreds of files, reviewing many modules). Bad fit: a few small edits — just do them directly with your own tools.
328
+
329
+ If it is a fit:
330
+
331
+ 1. Decompose the task, then write a JavaScript orchestration script. Top-level await and return are allowed. The script runs in a sandbox where ONLY these are available:
332
+ - \`subagent(task)\` or \`subagent({ task, model })\` — runs one sub-agent, resolves to its final output text
333
+ - \`parallel([() => ..., ...])\` — concurrent fan-out; each thunk's error becomes \`null\`; barrier semantics
334
+ - \`pipeline(items, [stage1, stage2, ...])\` — each item flows through all stages independently (prefer over parallel)
335
+ - \`log(...)\`, \`setTimeout/clearTimeout\`, standard JS builtins (Promise/JSON/Math/...)
336
+ - NO require/import/process/fetch/fs access — the static validator rejects scripts that try
337
+ 2. Every task string must be fully self-contained: which files to read/write, what "done" means, how to self-verify.
338
+ 3. Call the \`run_workflow\` tool with the full source as \`script\`. Read its report carefully; on failures fix the script, or rerun with \`script_path\` + \`resume: true\` to continue from saved progress.
339
+
340
+ Keep scripts deterministic (same order of subagent calls every run) so resume works. Summarize the outcome to the user afterwards in their language.
341
+ `;
342
+ const p = join(dir, "workflow.md");
343
+ if (!existsSync(p) || readFileSync(p, "utf8") !== content) {
344
+ writeFileSync(p, content);
345
+ }
346
+ }
300
347
  /**
301
348
  * pi 会把环境里的厂商密钥(ANTHROPIC_API_KEY 等)当作「已配置的 provider」,
302
349
  * /model 里冒出一大串没在用的模型(u1s1 又拦了 /login,配了也没法管理)。
package/dist/api.d.ts CHANGED
@@ -43,6 +43,11 @@ export interface ApiModel {
43
43
  cache_read: number | null;
44
44
  };
45
45
  }
46
+ /** 启动横幅公告(后台「全局设置」下发);url 可选。老网关没有该字段,undefined = 不显示。 */
47
+ export interface ApiAnnouncement {
48
+ text: string;
49
+ url?: string;
50
+ }
46
51
  /** 服务端能力开关;字段缺失(老网关)时按开启处理,保持现状。 */
47
52
  export interface ApiFeatures {
48
53
  web_search?: boolean;
@@ -54,6 +59,7 @@ export interface ApiFeatures {
54
59
  export interface ModelsResponse {
55
60
  models: ApiModel[];
56
61
  features: ApiFeatures;
62
+ announcement?: ApiAnnouncement | null;
57
63
  }
58
64
  export declare function fetchModels(cfg: CliConfig): Promise<ModelsResponse>;
59
65
  export interface ApiEndpoint {
package/dist/api.js CHANGED
@@ -18,7 +18,7 @@ export async function fetchModels(cfg) {
18
18
  if (!resp.ok)
19
19
  throw new Error(`服务端返回 ${resp.status},稍后再试`);
20
20
  const body = (await resp.json());
21
- return { models: body.data, features: body.features ?? {} };
21
+ return { models: body.data, features: body.features ?? {}, announcement: body.announcement };
22
22
  }
23
23
  /**
24
24
  * 拉取用户在云端配置的自定义模型端点(dashboard「自定义模型端点」卡片)。