Skip to content

Commit 05bf334

Browse files
authored
Merge pull request #5064 from loopx-project/codex/app-intent-inbox-plan
2 parents ea3ace4 + 40bb86c commit 05bf334

52 files changed

Lines changed: 2785 additions & 863 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/presentation/dashboard/package.json‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
"smoke:frontstage-route": "rm -rf /tmp/loopx-frontstage-route-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-frontstage-route-smoke smoke/frontstage-route-smoke.ts && node /tmp/loopx-frontstage-route-smoke/frontstage-route-smoke.js",
2828
"smoke:frontstage-share-bundle": "node ../../../examples/frontstage-share-bundle-smoke.mjs",
2929
"smoke:goal-order": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --skipLibCheck --strict --outDir node_modules/.cache/loopx-goal-order src/features/personal-workspace/goal-order.ts && node src/features/personal-workspace/goal-order.test.mjs",
30+
"smoke:goal-activity": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --skipLibCheck --strict --outDir node_modules/.cache/loopx-goal-activity src/features/personal-workspace/goal-activity.ts && node src/features/personal-workspace/goal-activity.test.mjs",
31+
"smoke:proposal-recency": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --skipLibCheck --strict --outDir node_modules/.cache/loopx-proposal-recency src/features/personal-workspace/proposal-recency.ts && node src/features/personal-workspace/proposal-recency.test.mjs",
3032
"smoke:home-browser": "node ../../../examples/dashboard-home-browser-smoke.mjs",
3133
"smoke:home-route": "rm -rf /tmp/loopx-home-route-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-home-route-smoke smoke/home-route-smoke.ts && node /tmp/loopx-home-route-smoke/home-route-smoke.js",
3234
"smoke:delegation-preflight": "rm -rf node_modules/.cache/loopx-delegation-preflight-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --jsx react-jsx --skipLibCheck --strict --rootDir . --outDir node_modules/.cache/loopx-delegation-preflight-smoke smoke/delegation-preflight-smoke.tsx src/data/delegation-preflight.ts src/features/personal-workspace/delegation-preflight-status.tsx && node node_modules/.cache/loopx-delegation-preflight-smoke/smoke/delegation-preflight-smoke.js",
33-
"smoke:personal-workspace": "npm run smoke:goal-order && npm run smoke:delegation-preflight && node src/features/personal-workspace/workspace-theme.test.mjs && node src/features/personal-workspace/personal-workspace-contract.test.mjs && node ../../../examples/personal-workspace-browser-smoke.mjs",
35+
"smoke:personal-workspace": "npm run smoke:goal-order && npm run smoke:goal-activity && npm run smoke:proposal-recency && npm run smoke:delegation-preflight && node src/features/personal-workspace/workspace-theme.test.mjs && node src/features/personal-workspace/personal-workspace-contract.test.mjs && node ../../../examples/personal-workspace-browser-smoke.mjs",
3436
"smoke:workspace-locale": "LOOPX_PERSONAL_WORKSPACE_SCENARIO=workspace-locale node ../../../examples/personal-workspace-browser-smoke.mjs",
35-
"smoke:personal-workspace-packaged": "npm run smoke:goal-order && npm run smoke:delegation-preflight && node src/features/personal-workspace/workspace-theme.test.mjs && node src/features/personal-workspace/personal-workspace-contract.test.mjs && LOOPX_PERSONAL_WORKSPACE_PACKAGED=1 LOOPX_PLAYWRIGHT_PACKAGE=\"$PWD/node_modules/playwright\" node ../../../examples/personal-workspace-browser-smoke.mjs",
36-
"smoke:personal-workspace-router": "rm -rf /tmp/loopx-personal-workspace-router-smoke && tsc --ignoreConfig --target ES2022 --module commonjs --moduleResolution node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-personal-workspace-router-smoke smoke/personal-workspace-router-smoke.ts src/features/personal-workspace/personal-workspace-router.ts && node /tmp/loopx-personal-workspace-router-smoke/smoke/personal-workspace-router-smoke.js",
37+
"smoke:personal-workspace-packaged": "npm run smoke:goal-order && npm run smoke:goal-activity && npm run smoke:proposal-recency && npm run smoke:delegation-preflight && node src/features/personal-workspace/workspace-theme.test.mjs && node src/features/personal-workspace/personal-workspace-contract.test.mjs && LOOPX_PERSONAL_WORKSPACE_PACKAGED=1 LOOPX_PLAYWRIGHT_PACKAGE=\"$PWD/node_modules/playwright\" node ../../../examples/personal-workspace-browser-smoke.mjs",
38+
"smoke:todo-resume-condition": "rm -rf /tmp/loopx-todo-resume-condition-smoke && tsc --ignoreConfig --target ES2022 --module commonjs --moduleResolution node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-todo-resume-condition-smoke smoke/todo-resume-condition-smoke.ts src/features/personal-workspace/todo-resume-condition.ts && node /tmp/loopx-todo-resume-condition-smoke/smoke/todo-resume-condition-smoke.js",
3739
"smoke:presentation-surface-schema": "rm -rf /tmp/loopx-presentation-surface-schema-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --resolveJsonModule --esModuleInterop --outDir /tmp/loopx-presentation-surface-schema-smoke smoke/presentation-surface-schema-smoke.ts src/data/status.ts src/data/decision-research.ts src/data/goal-channel-frontstage.ts && NODE_PATH=\"$PWD/node_modules\" node /tmp/loopx-presentation-surface-schema-smoke/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.js",
3840
"smoke:projection-localization": "rm -rf /tmp/loopx-projection-localization-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-projection-localization-smoke smoke/projection-localization-smoke.ts src/features/personal-workspace/projection-localization.ts && node /tmp/loopx-projection-localization-smoke/smoke/projection-localization-smoke.js",
3941
"smoke:pwa-bundle": "python3 ../../../examples/dashboard-pwa-bundle-smoke.py",

‎apps/presentation/dashboard/smoke/personal-workspace-router-smoke.ts‎

Lines changed: 0 additions & 72 deletions
This file was deleted.

‎apps/presentation/dashboard/smoke/projection-localization-smoke.ts‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
type Values = Record<string, string | number>;
77

88
const english = {
9-
"projection.agentAdvancingGoal": "Agent is advancing the current Goal",
9+
"projection.agentWorkQueued": "Agent work is queued for this Goal",
1010
"projection.agentIdle": "Nothing needs your attention",
1111
"projection.agentNeedsDecision": "Agent is waiting for your decision",
1212
"projection.agentPreparingNextStep": "Agent is preparing the next step",
@@ -21,7 +21,7 @@ const english = {
2121
} as const;
2222

2323
const chinese = {
24-
"projection.agentAdvancingGoal": "Agent 正在推进当前 Goal",
24+
"projection.agentWorkQueued": "这个 Goal 有待 Agent 推进的工作",
2525
"projection.agentIdle": "暂无需要你处理",
2626
"projection.agentNeedsDecision": "Agent 等待你的决定",
2727
"projection.agentPreparingNextStep": "Agent 正在整理下一步",
@@ -63,23 +63,23 @@ const en = translator(english);
6363
const zhCN = translator(chinese);
6464

6565
equal(
66-
projectionSentence("loopx check --format json", en, "projection.agentAdvancingGoal"),
67-
"Agent is advancing the current Goal",
68-
"English command-like projection uses the localized advancing fallback",
66+
projectionSentence("loopx check --format json", en, "projection.agentWorkQueued"),
67+
"Agent work is queued for this Goal",
68+
"English command-like projection uses the localized queued-work fallback",
6969
);
7070
equal(
71-
projectionSentence("loopx check --format json", zhCN, "projection.agentAdvancingGoal"),
72-
"Agent 正在推进当前 Goal",
73-
"Chinese command-like projection preserves the localized advancing fallback",
71+
projectionSentence("loopx check --format json", zhCN, "projection.agentWorkQueued"),
72+
"这个 Goal 有待 Agent 推进的工作",
73+
"Chinese command-like projection preserves the localized queued-work fallback",
7474
);
7575
equal(
76-
projectionSentence("Review the project-specific adapter signal", en, "projection.agentAdvancingGoal"),
76+
projectionSentence("Review the project-specific adapter signal", en, "projection.agentWorkQueued"),
7777
"Review the project-specific adapter signal",
7878
"Source-authored projection text remains unchanged",
7979
);
8080

8181
equal(agentStatusSentence("needs_you", en), "Agent is waiting for your decision", "English needs-you status");
82-
equal(agentStatusSentence("advancing", en), "Agent is advancing the current Goal", "English advancing status");
82+
equal(agentStatusSentence("queued", en), "Agent work is queued for this Goal", "English queued-work status");
8383
equal(agentStatusSentence("waiting_external", en), "Waiting for an external condition", "English external-wait status");
8484
equal(agentStatusSentence("idle", en), "Nothing needs your attention", "English idle status");
8585
equal(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { parseTodoResumeCondition } from "../src/features/personal-workspace/todo-resume-condition.js";
2+
3+
for (const condition of ["todo_done:todo_release", "pr_merged:example/project#42", "capacity_available:worker", "resume_at:2026-10-01T09:00:00Z"]) {
4+
if (parseTodoResumeCondition(condition) !== condition.toLowerCase()) throw new Error(`Supported resume condition rejected: ${condition}`);
5+
}
6+
for (const value of ["tomorrow", "owner_resume", "pr_merged:#0", "todo_done:", "resume_at:2026-10-01"]) {
7+
if (parseTodoResumeCondition(value) !== null) throw new Error(`Unsupported resume condition admitted: ${value}`);
8+
}
9+
console.log("todo-resume-condition-smoke: ok");

‎apps/presentation/dashboard/src/data/chat.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,8 @@ export type ChatSessionSummary = {
661661
updated_at: string;
662662
last_activity_at: string;
663663
resumable: boolean;
664+
session_mode?: string;
665+
host_surface?: string | null;
664666
manager_runtime?: ManagerRuntimeSessionReadback | null;
665667
};
666668

‎apps/presentation/dashboard/src/data/status.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,26 @@ export const runGoalSchema = z.object({
521521
coordination: z.object({
522522
agent_model: z.string().optional().nullable(),
523523
registered_agents: z.array(z.string()).optional().default([]),
524+
// Opaque host thread ids stay out of the App state.
525+
thread_agent_bindings: z.array(z.object({
526+
agent_id: z.string().optional().nullable(),
527+
host_surface: z.string().optional().nullable(),
528+
})).optional().default([]).catch([]),
524529
}).optional().nullable(),
530+
host_thread_activity: z.object({
531+
observed_at: z.string().optional().nullable(),
532+
// Older or malformed observations cannot prove that every binding was read.
533+
completeness: z.enum(["complete", "incomplete"]).catch("incomplete").default("incomplete"),
534+
threads: z.array(z.object({
535+
agent_id: z.string().optional().nullable(),
536+
host_surface: z.string(),
537+
state: z.enum(["turn_open", "idle", "archived", "unknown"]).catch("unknown"),
538+
reason: z.string().optional().nullable(),
539+
turn_started_at: z.string().optional().nullable(),
540+
last_turn_ended_at: z.string().optional().nullable(),
541+
last_event_at: z.string().optional().nullable(),
542+
})).optional().default([]),
543+
}).optional().nullable().catch(null),
525544
index_exists: z.boolean().optional().default(false),
526545
raw_index_records: z.number().optional().default(0),
527546
unique_runs: z.number().optional().default(0),

‎apps/presentation/dashboard/src/features/personal-workspace/channel-header.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Bot, Eye, Menu, RefreshCw, SlidersHorizontal } from "lucide-react";
2+
import { GoalActivityChip } from "./goal-activity-view";
23

34
import { localizedGoalState, useWorkspaceI18n } from "./i18n";
45
import type { ManagerChannelBinding, ManagerRuntimeSessionReadback } from "../../data/chat";
@@ -135,7 +136,7 @@ export function ChannelHeader({
135136
<button aria-expanded={mobileNavigationOpen ?? false} aria-label={t("header.openGoalNavigation")} className="personal-icon-button personal-mobile-menu" onClick={onOpenNavigation} type="button"><Menu size={18} /></button>
136137
<div className="personal-channel-title">
137138
<h1>{selectedGoal?.title ?? t("header.manager")}</h1>
138-
{selectedGoal && !selectedGoal.loadState && !["安静运行", "推进中"].includes(selectedGoal.state) ? <p>{localizedGoalState(selectedGoal.state, locale)}</p> : null}
139+
{selectedGoal && !selectedGoal.loadState ? <p className="personal-channel-activity"><GoalActivityChip goal={selectedGoal} /></p> : null}
139140
{!selectedGoal && managerChannelBinding ? (
140141
<p className="personal-manager-execution">
141142
<span className={managerExecutionUnavailable ? "personal-execution-chip is-unavailable" : "personal-execution-chip"}>

0 commit comments

Comments
 (0)