diff --git a/packages/core/src/agent.ts b/packages/core/src/agent.ts index 4223adf..cf60604 100644 --- a/packages/core/src/agent.ts +++ b/packages/core/src/agent.ts @@ -181,7 +181,7 @@ export class Agent { */ async createSession(opts: CreateSessionOptions = {}): Promise { // Model is validated first (before creating the Workspace, so failure leaves no - // temp directory behind): the reference must be the complete (provider, model_id) + // temporary workspace behind): the reference must be the complete (provider, model_id) // pair — the config's unique key — and must name an entry in the Project config; a // reference outside the config throws immediately rather than passing silently, // otherwise credentials, pricing, and the context window would all be unavailable. @@ -217,7 +217,7 @@ export class Agent { // An explicit Workspace must already exist as a directory: if it // doesn't, throw rather than auto-create (to avoid a typo silently working in - // the wrong location); a temp Workspace is only created when unspecified. + // the wrong location); a temporary workspace is only created when unspecified. let workspaceDir: string; if (opts.workspaceDir) { workspaceDir = path.resolve(opts.workspaceDir); @@ -226,7 +226,7 @@ export class Agent { stat = await fs.stat(workspaceDir); } catch { throw new Error( - `Workspace does not exist: ${workspaceDir}. Specify an existing directory, or omit the Workspace to use a temporary directory.`, + `Workspace does not exist: ${workspaceDir}. Specify an existing directory, or omit the Workspace to use a temporary workspace.`, ); } if (!stat.isDirectory()) { diff --git a/packages/core/src/internal/session-support.ts b/packages/core/src/internal/session-support.ts index 3a4bd0e..5ffaac8 100644 --- a/packages/core/src/internal/session-support.ts +++ b/packages/core/src/internal/session-support.ts @@ -91,7 +91,7 @@ export async function createTempWorkspace( await fs.mkdir(base, { recursive: true }); // The final directory must use a non-recursive mkdir: recursive mkdir succeeds // silently when the directory already exists, which would put a new Session into - // an existing temp Workspace; EEXIST means an id collision, so retry with a new id. + // an existing temporary workspace; EEXIST means an id collision, so retry with a new id. for (let attempt = 0; attempt < MAX_TMP_ID_ATTEMPTS; attempt++) { const dir = path.join(base, `tmp-${randomUUID().slice(0, 8)}`); try { diff --git a/packages/core/src/state/project-config.ts b/packages/core/src/state/project-config.ts index 3934709..c1fc4e3 100644 --- a/packages/core/src/state/project-config.ts +++ b/packages/core/src/state/project-config.ts @@ -128,7 +128,7 @@ export const DEFAULT_CHAT_THINKING_LEVELS: readonly DefaultChatThinkingLevel[] = * New-chat defaults (`[default_chat]`): per-Project prefill for newly created chats. * Every key is optional and independent: * - `agent_id`: the Agent preselected on the draft page (must name an existing Agent); - * - `workspace`: the prefilled Workspace directory (absent/empty = auto temp directory); + * - `workspace`: the prefilled Workspace directory (absent/empty = a temporary workspace); * - `approval_mode`: the prefilled approval mode (absent = the built-in "allow-all"); * - `thinking_level`: fallback thinking level for Agents whose config has no explicit * `model.thinking_level` (see Agent's thinking-level resolution chain in agent.ts). diff --git a/packages/core/test/agent.test.ts b/packages/core/test/agent.test.ts index 05495bc..6b5d5fc 100644 --- a/packages/core/test/agent.test.ts +++ b/packages/core/test/agent.test.ts @@ -5,7 +5,7 @@ * Regression: an explicitly given Workspace must be an existing directory. When it * does not exist, a clear error must be thrown rather than auto-creating it, and bash must not * be started with an invalid cwd after Session creation, which would throw a misleading - * `spawn bash ENOENT`. A temp directory is only created when no Workspace is specified. + * `spawn bash ENOENT`. A temporary workspace is only created when no Workspace is specified. * * vault: the Agent vault's (agent_state/.vault.toml) **key names** are * injected into the assembled system prompt; values are never injected. @@ -131,7 +131,7 @@ describe("Agent.createSession workspace handling", () => { const ws = path.join(tmpRoot, "ws-bad-model"); await fs.mkdir(ws, { recursive: true }); // A reference outside the config is not silently allowed (the unique key is provider + - // model_id); the error is thrown before creating the temp Workspace. + // model_id); the error is thrown before creating the temporary workspace. await expect( agent.createSession({ workspaceDir: ws, diff --git a/packages/core/test/workspace.test.ts b/packages/core/test/workspace.test.ts index ce42330..44579b6 100644 --- a/packages/core/test/workspace.test.ts +++ b/packages/core/test/workspace.test.ts @@ -5,7 +5,7 @@ * `/workspaces/`. * - The id is checked for collisions within `workspaces/`: on conflict with an existing * directory (EEXIST), it regenerates rather than reusing the existing directory; once - * retries are exhausted, it throws instead of silently falling back to an old temp Workspace. + * retries are exhausted, it throws instead of silently falling back to an old temporary workspace. */ import fs from "node:fs/promises"; import os from "node:os"; diff --git a/packages/docs/content/server-api.en.md b/packages/docs/content/server-api.en.md index 7923659..850842f 100644 --- a/packages/docs/content/server-api.en.md +++ b/packages/docs/content/server-api.en.md @@ -135,7 +135,7 @@ Schedule writes are owner-only. A task in new-Session mode carries `modelId` and | POST | /agents/:agentId/sessions | Create a Session: `{modelId?, provider?, workspace?, approvalMode?}` → 201 | | GET | /dirs?path= | Server-side directory browser (backs the Workspace picker) | -On Session creation, `modelId` and `provider` are both-or-neither: send the complete pair to pick a model, or omit both to take the Project's default model — one without the other is a 400. The Workspace defaults to an auto-created temporary directory, and the approval mode defaults to `allow-all`. +On Session creation, `modelId` and `provider` are both-or-neither: send the complete pair to pick a model, or omit both to take the Project's default model — one without the other is a 400. The Workspace defaults to an auto-created temporary workspace, and the approval mode defaults to `allow-all`. ### Usage and Traces (Agent Level) diff --git a/packages/docs/content/server-api.zh.md b/packages/docs/content/server-api.zh.md index b97ca3d..3cd94e1 100644 --- a/packages/docs/content/server-api.zh.md +++ b/packages/docs/content/server-api.zh.md @@ -135,7 +135,7 @@ Schedule 写操作仅限 Owner。新建 Session 模式的任务,`modelId` 与 | POST | /agents/:agentId/sessions | 创建 Session:`{modelId?, provider?, workspace?, approvalMode?}` → 201 | | GET | /dirs?path= | 服务器端目录浏览(Workspace 选择器数据源) | -创建 Session 时,`modelId` 与 `provider` 要么成对给出、要么都不给:给出完整二元组即指定模型,两个都省略则取 Project 默认模型,只给一个返回 400。Workspace 默认自动创建临时目录,审批模式默认 `allow-all`。 +创建 Session 时,`modelId` 与 `provider` 要么成对给出、要么都不给:给出完整二元组即指定模型,两个都省略则取 Project 默认模型,只给一个返回 400。Workspace 默认自动创建临时工作区,审批模式默认 `allow-all`。 ### 用量与 Trace(Agent 级) diff --git a/packages/docs/content/sessions-and-traces.en.md b/packages/docs/content/sessions-and-traces.en.md index 543bb74..cc7bf75 100644 --- a/packages/docs/content/sessions-and-traces.en.md +++ b/packages/docs/content/sessions-and-traces.en.md @@ -13,7 +13,7 @@ Six levels: Project → Agent → Workspace → Session → Task → Request. | --- | --- | | Project | Top-level unit organizing Agents; owns the model and credential configuration; in the multi-user Web setup, users and Projects are many-to-many | | Agent | The executing subject; has exactly one Agent State (a persistent directory); one Agent can serve many Workspaces | -| Workspace | The working directory of one run — the only file scope the model sees; an explicit `workspaceDir` must already exist, otherwise a temp Workspace `workspaces/tmp-<8hex>` is created | +| Workspace | The working directory of one run — the only file scope the model sees; an explicit `workspaceDir` must already exist, otherwise a temporary Workspace `workspaces/tmp-<8hex>` is created | | Session | A continuous conversation under one (Agent, Workspace); model and Workspace are locked at Session creation; ids look like `session-YYYY-MM-DD-HH-mm-ss-<8hex>` | | Task | One execution goal started by one Prompt; consists of one or more consecutive Requests | | Request | One LLM API call: context and tool definitions in, streamed output out | @@ -39,7 +39,7 @@ The data root is the `PENGUIN_HOME` environment variable, defaulting to `~/.peng │ # convention, not a path the code creates, so tooling is │ # installed once for any task; project dependencies stay │ # in the project - ├── workspaces/ # temp Workspaces (tmp-<8hex>) + ├── workspaces/ # temporary Workspaces (tmp-<8hex>) ├── benchmarks/ # capability Benchmark cases and scores └── snapshots/ # Agent State version snapshots ``` diff --git a/packages/server/src/api/types.ts b/packages/server/src/api/types.ts index 852d5a2..fc28d64 100644 --- a/packages/server/src/api/types.ts +++ b/packages/server/src/api/types.ts @@ -391,7 +391,7 @@ export interface DefaultModelResponse { export interface ChatDefaultsDto { /** Preselected Agent; must reference an existing Agent of the Project (400 unknown_agent). */ agentId?: string; - /** Prefilled Workspace directory; absent/empty = auto temp directory. */ + /** Prefilled Workspace directory; absent/empty = a temporary workspace. */ workspace?: string; /** Prefilled approval mode; absent = the built-in "allow-all". */ approvalMode?: ApprovalMode; diff --git a/packages/server/src/http/routes/chat-defaults.ts b/packages/server/src/http/routes/chat-defaults.ts index 1c69ddf..8966588 100644 --- a/packages/server/src/http/routes/chat-defaults.ts +++ b/packages/server/src/http/routes/chat-defaults.ts @@ -47,7 +47,7 @@ export function chatDefaultsRoutes(deps: AppDeps): Hono { } // Not validated as an existing directory on purpose: the default is a prefill, and the - // directory is (re)checked when a Session is actually created. "" = clear (auto temp). + // directory is (re)checked when a Session is actually created. "" = clear (temporary workspace). const workspace = optionalString(body, "workspace", { maxLen: 4096, label: "workspace" }); if (workspace !== undefined && workspace !== "") req.workspace = workspace; diff --git a/packages/server/src/runtime/schedule-file.ts b/packages/server/src/runtime/schedule-file.ts index 7db9d53..0f3779e 100644 --- a/packages/server/src/runtime/schedule-file.ts +++ b/packages/server/src/runtime/schedule-file.ts @@ -33,7 +33,7 @@ export interface ScheduleDefinition { endAtMs?: number; /** The target Session to bind to; defaults to creating a new Session each time. */ sessionId?: string; - /** Workspace for new-Session mode (same semantics as manually starting a session; auto-creates a temp directory if unspecified). */ + /** Workspace for new-Session mode (same semantics as manually starting a session; a temporary workspace is auto-created if unspecified). */ workspace?: string; /** Model for new-Session mode (upstream id, always paired with provider; omit both for the Project's default reference). */ modelId?: string; diff --git a/packages/server/src/services/workspace-guard.ts b/packages/server/src/services/workspace-guard.ts index d61eb4c..da6d9f0 100644 --- a/packages/server/src/services/workspace-guard.ts +++ b/packages/server/src/services/workspace-guard.ts @@ -8,7 +8,7 @@ * reachability governed by the file permissions of the OS account running the * service. * When no Workspace is specified, this module isn't involved (the SDK creates its - * own temporary directory). + * own temporary workspace). */ import fs from "node:fs/promises"; import { HttpError } from "../http/errors.js"; @@ -26,7 +26,7 @@ export async function assertWorkspaceAllowed(args: { workspace: string }): Promi throw new HttpError( 400, "workspace_not_found", - `Workspace does not exist or is inaccessible: ${args.workspace}. Specify an existing directory, or leave it empty to use a temporary directory.`, + `Workspace does not exist or is inaccessible: ${args.workspace}. Specify an existing directory, or leave it empty to use a temporary workspace.`, ); } const stat = await fs.stat(ws); diff --git a/packages/server/test/session-index.test.ts b/packages/server/test/session-index.test.ts index d901ea6..0526793 100644 --- a/packages/server/test/session-index.test.ts +++ b/packages/server/test/session-index.test.ts @@ -84,7 +84,7 @@ describe("session-index", () => { } }); - it("creating a Session: auto temp Workspace by default, allow-all default, shows in the list", async () => { + it("creating a Session: temporary Workspace by default, allow-all default, shows in the list", async () => { await configureModels(); const res = await api.post(base(), {}); expect(res.status).toBe(201); @@ -321,8 +321,8 @@ describe("session-index", () => { expect((await list("")).workspaceCounts).toBeUndefined(); // The per-Workspace breakdown accompanies the totals and sums back to them: the - // subagent Session sits alone in its path; every other row lives in its own auto - // temp directory. + // subagent Session sits alone in its path; every other row lives in its own + // temporary workspace. const byWorkspace = full.workspaceCounts!; expect(byWorkspace["/tmp/w-sub"]).toEqual({ active: 0, diff --git a/packages/skills/skills/penguin-sdk/SKILL.md b/packages/skills/skills/penguin-sdk/SKILL.md index 3e20a48..786d6d6 100644 --- a/packages/skills/skills/penguin-sdk/SKILL.md +++ b/packages/skills/skills/penguin-sdk/SKILL.md @@ -3,8 +3,8 @@ name: penguin-sdk description: Build AI apps on the Penguin Harness SDK — self-contained projects, the createSession/run streaming loop with thinking and image messages, and a complete RAG recipe that ingests documents into a knowledge base and answers with citations behind a web UI. short_description: Build AI and RAG apps on the Penguin Harness SDK. short_description_zh: 基于 Penguin SDK 构建 AI 与 RAG 应用。 -version: 18 -updated: 2026-07-30T11:10:00Z +version: 19 +updated: 2026-08-06T00:00:00Z --- # Penguin Harness SDK @@ -97,7 +97,7 @@ rl.close(); session.dispose(); ``` -- `createSession({ workspaceDir, provider, modelId })` — `workspaceDir` must already exist (omit for an auto temp dir); the model reference is the `(provider, modelId)` pair, so pass both to pick a configured model or neither for the project default — passing one alone throws. +- `createSession({ workspaceDir, provider, modelId })` — `workspaceDir` must already exist (omit for a temporary workspace); the model reference is the `(provider, modelId)` pair, so pass both to pick a configured model or neither for the project default — passing one alone throws. - The `approve` callback gates every tool call; **omitting it denies everything**. - `opts.thinkingLevel` (`"none" | "low" | "medium" | "high" | "xhigh"`) overrides the agent's default (`model.thinking_level` in `system_config.yaml`) for this turn only — raise it for hard questions, drop it for latency-sensitive calls like titling or classification. - Session lifetime is the app's memory model: reuse one Session for a stateful chat (context accumulates, as above), create one per request for stateless QA (the RAG recipe below); either way call `session.dispose()` when done to release background processes. diff --git a/packages/web/e2e/draft.spec.mjs b/packages/web/e2e/draft.spec.mjs index 92ba191..8cd190b 100644 --- a/packages/web/e2e/draft.spec.mjs +++ b/packages/web/e2e/draft.spec.mjs @@ -4,7 +4,7 @@ * the first message is sent, and all four selections land faithfully in its meta; * - the draft auto-caches (body persisted via debounce): after a page reload, both the body and * the selections are restored, and the cache clears once sending succeeds; - * - the sidebar defaults to grouping by Workspace: auto temp directories merge into one + * - the sidebar defaults to grouping by Workspace: temporary workspaces merge into one * "临时工作区" group, a named directory groups under its basename, and that group header's * "+" pre-fills the draft's Workspace (via router state, applied once per navigation — a * manual change made afterwards survives a reload instead of being re-overridden); @@ -171,8 +171,11 @@ test("draft: pick model/approval -> reload restores them -> send creates the ses ); // —— Default grouping: the sidebar groups Sessions by Workspace — the session just created - // used the auto temp directory, so it lands in the merged "临时工作区" group. —— - await expect(page.getByText("临时工作区")).toBeVisible(); + // used an auto-created temporary workspace, so it lands in the merged "临时工作区" group. + // Scoped to the sidebar (