@xopcai/xopc 0.0.336 → 0.0.338
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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-NNn5LiRh.js → agent-avatar-dicebear-D7lwnzGf.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-DNYmmcXR.js → agent-defaults-settings-panel-Bsf_C5G-.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-plugin-dialog-DfAd5ptC.js → agent-plugin-dialog-D1bd54F4.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-DEgksLoh.js → agents-D9LauN1U.js} +3 -3
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BR-Ks3tk.js → app-management-settings-panel-Blp7cgN9.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DQn5060f.js → appearance-settings-CKEHZAl0.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BghyAP7f.js → apps-page-CHCvTpXO.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-DSyujAeW.js → archive-plugin-BTQaxZoS.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-dl2URNWU.js → automations-page-DT_SzVIu.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-C_3pzyHa.js → automations-workspace-xyYt1P_F.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-Bi6hXKEs.js → binary-plugins-CeeqvrXF.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-aqBwqSqa.js → block-editor-B5Si55pP.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-BxLzYDlU.js → browser-automations-page-DApYWSvZ.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-wiVToOs2.js → browser-settings-page-B4FRZt79.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-page-9SxFc1Gk.js → capabilities-page-Dm3rO9D9.js} +2 -2
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-6o3ePBVe.js → capabilities-settings-panel-BxWC1fto.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-header-actions-o7tnD40O.js → capability-header-actions-ulVgiGk5.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-BiDkmHQX.js → channels-CxjiPi_K.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DgaRuyCk.js → chat-terminal-dock-k7s5v_aC.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-settings-page-BScTGz9r.js → computer-settings-page-B6aKe8Pz.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-D19h4o3H.js → connector-service-page-DS_dCuYu.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-nb20ZtXB.js → connectors-page-CbLxkIGU.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-4XKcj75n.js → date-picker-DOl4D6Og.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-BLLIIM2j.js → dependency-picker-DTZpqUW9.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-F-odgilG.js → desktop-pet-A9AmyZFd.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-C1bi6P68.js → desktop-pet-settings-D4NMQfeC.js} +1 -1
- package/dist/gateway/static/root/assets/{device-pairing-wizard-C8brKN1N.js → device-pairing-wizard-B19IahuA.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BQROUAVR.js → directory-picker-path-field-D_92XGjD.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-j6UKcafs.js → extension-debug-page-CJEVTdVQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B-MC_llQ.js → extension-page-Bo_QfERv.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-E7iPqGV_.js → extension-settings-page-DyQKVwEg.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-CxhocvFl.js → gateway-settings-Cm57iUdQ.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-DKJTrzRz.js → home-page-NBbSjN9G.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-BH0bK4Fi.js → imports-page-B9T8hM43.js} +1 -1
- package/dist/gateway/static/root/assets/{index-Z_w672TD.js → index-B-NICmRj.js} +9 -9
- package/dist/gateway/static/root/assets/index-Bd7mDZFV.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DqYlPK6e.js → keyboard-shortcuts-settings-DU3r7EWf.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-DJFEtiQ-.js → local-app-workbench-page-ChpwIJTp.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-soLqlAnz.js → local-apps-page-Cz8SE9jo.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CG21jjyw.js → logs-page-1oTbkOs_.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-lZjA5aEo.js → management-settings-BXeXgpGe.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Bx67LlgO.js → media-plugins-DU8A_g9F.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-panel-C-uwlkj6.js → note-detail-panel-D4KpPyvg.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-page-BvJNHWMx.js → notes-page-DvUYRsn1.js} +1 -1
- package/dist/gateway/static/root/assets/{page-context-capture-button-X1LphhT2.js → page-context-capture-button-BmpkysKb.js} +1 -1
- package/dist/gateway/static/root/assets/{page-tabs-Bvuo9Cp9.js → page-tabs-BYVaSh2t.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-CnosDbXg.js → preview-open-alternatives-C3EhH0bN.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DH38UFyT.js → product-open-page-CR5vTalE.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-DzS67sf6.js → project-detail-page-5e5nW6aK.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-D8tBTON4.js → projects-page-BEcT_inq.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-Bwsg9beH.js → remote-access-hub-B1qvhjS4.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BcTGjpqr.js → runtime-tools-settings-panel-B_0CfBAT.js} +1 -1
- package/dist/gateway/static/root/assets/{scenes-page-jbTHblQV.js → scenes-page-DUL9nosj.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BtuMUmjZ.js → schema-form-va7QWGEA.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-Dm2qIlJZ.js → sessions-page-vVCF7_fY.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BArcldzX.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-6QQu_bi3.js → settings-form-section-CFLiI9wl.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-B000AkmV.js → settings-page-uNvPtLCL.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-Ogru9NdY.js → setup-status-panel-_w4HzIN6.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BMO2ZoqU.js → share-preview-page-ByyeLleG.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-CtmBtL1f.js → shares-settings-BiLA03S-.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-api-DzFmRoGt.js → skill-api-DXOq4iWa.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-DcyuV6CY.js → skill-reload-api-D2uzVAZq.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-DQBfVKZv.js → skills-page-BSnyNWx-.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-CYr7jyqK.js → system-settings-panel-BPoF82eS.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-CwxfwNqK.js → task-detail-page-DvVPVptc.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-COxKjwYF.js → tunnel-api-CA92GwfO.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-CJDBoCpM.js → usage-page-B7F4u0TA.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Tiykntd0.js → use-autosave-Ca0tBkcs.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-BhGePvWd.js → user-model-page-aeTxECGB.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-Bny9WMTa.js → voice-api-key-field-BL6CNWHA.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-B6FMtX3w.js → work-discovery-overlay-CSc9Xv9J.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DoOMpqPg.js → workflow-run-setup-panel-hho2_zza.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-b2v3lMJ1.js → workflows-page-N--cEC4e.js} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/index.js +2 -0
- package/dist/packages/gateway-contract/src/mobile-user-understanding.js +140 -0
- package/dist/src/agent/source-context/index.d.ts +1 -0
- package/dist/src/agent/source-context/index.js +2 -1
- package/dist/src/agent/source-context/types.d.ts +2 -2
- package/dist/src/agent/source-context/types.js +1 -1
- package/dist/src/agent/source-context/user-assertion-context.d.ts +2 -0
- package/dist/src/agent/source-context/user-assertion-context.js +30 -0
- package/dist/src/cli/index.js +1 -1
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +2 -2
- package/dist/src/gateway/hono/routes/sessions.js +7 -0
- package/dist/src/gateway/hono/routes/user-model.js +202 -0
- package/dist/src/gateway/run-loop.js +1 -1
- package/dist/src/gateway/security/gateway-scopes.js +3 -0
- package/dist/src/gateway/service/session-input-coordinator.js +1 -1
- package/dist/src/gateway/service.js +6 -1
- package/dist/src/user-model/goals.d.ts +1 -1
- package/dist/src/user-model/goals.js +2 -1
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/index-DbLEkdNg.css +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-9sku1sUP.js +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getAssertionSlot, getUserAssertion, listUserAssertionSources } from "../../user-model/repository.js";
|
|
2
|
+
import { canUseAssertion } from "../../user-model/usage-policy.js";
|
|
3
|
+
import "../../user-model/index.js";
|
|
4
|
+
//#region src/agent/source-context/user-assertion-context.ts
|
|
5
|
+
function buildUserAssertionAgentContext(assertionId, expectedVersion, agentId) {
|
|
6
|
+
const assertion = getUserAssertion(assertionId);
|
|
7
|
+
const slot = assertion ? getAssertionSlot(assertion.slotId) : void 0;
|
|
8
|
+
if (!assertion || !slot || slot.scope.type !== "global" || expectedVersion && expectedVersion !== String(assertion.recordedAt) || !canUseAssertion(assertion, Date.now(), {
|
|
9
|
+
use: "answer",
|
|
10
|
+
agentId
|
|
11
|
+
})) return null;
|
|
12
|
+
const sources = listUserAssertionSources([assertion.id]).get(assertion.id) ?? [];
|
|
13
|
+
return {
|
|
14
|
+
kind: "user_assertion",
|
|
15
|
+
sourceId: assertion.id,
|
|
16
|
+
version: String(assertion.recordedAt),
|
|
17
|
+
title: assertion.statement,
|
|
18
|
+
text: JSON.stringify({
|
|
19
|
+
id: assertion.id,
|
|
20
|
+
statement: assertion.statement,
|
|
21
|
+
predicate: slot.predicate,
|
|
22
|
+
scope: slot.scope,
|
|
23
|
+
status: assertion.status,
|
|
24
|
+
authority: assertion.authority,
|
|
25
|
+
sources
|
|
26
|
+
}, null, 2)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { buildUserAssertionAgentContext };
|
package/dist/src/cli/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { version } from "../../package.js";
|
|
3
|
-
import { bootstrapApplicationStateSync } from "../bootstrap/application-state.js";
|
|
4
3
|
import { isHelpOrVersionInvocation } from "./argv.js";
|
|
5
4
|
import { ROOT_COMMAND_DESCRIPTION } from "./command-manifest.js";
|
|
6
5
|
import { loadAllCommands, resolveCommandName, tryLoadCommand } from "./command-loaders.js";
|
|
7
6
|
import { getContextWithOpts, parsedOpts } from "./context.js";
|
|
7
|
+
import { bootstrapApplicationStateSync } from "../bootstrap/application-state.js";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
//#region src/cli/index.ts
|
|
10
10
|
/** Command wiring and `program.parse`; executable entry is `bin.ts` (log preset before logger init). */
|
|
@@ -73,7 +73,7 @@ export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteD
|
|
|
73
73
|
}[];
|
|
74
74
|
contextSnapshots?: {
|
|
75
75
|
refId?: string;
|
|
76
|
-
kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "task" | "file" | "session" | "mcp_resource" | "browser_tab" | "browser_page" | "app_context";
|
|
76
|
+
kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "task" | "file" | "session" | "mcp_resource" | "browser_tab" | "browser_page" | "app_context" | "user_assertion";
|
|
77
77
|
sourceId: string;
|
|
78
78
|
version: string;
|
|
79
79
|
title: string;
|
|
@@ -217,7 +217,7 @@ export declare function replaceLatestSessionTurn(c: Context, deps: Authenticated
|
|
|
217
217
|
}[];
|
|
218
218
|
contextSnapshots?: {
|
|
219
219
|
refId?: string;
|
|
220
|
-
kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "task" | "file" | "session" | "mcp_resource" | "browser_tab" | "browser_page" | "app_context";
|
|
220
|
+
kind: import("../../../agent/source-context/types.js").SessionSourceBinding["kind"] | "task" | "file" | "session" | "mcp_resource" | "browser_tab" | "browser_page" | "app_context" | "user_assertion";
|
|
221
221
|
sourceId: string;
|
|
222
222
|
version: string;
|
|
223
223
|
title: string;
|
|
@@ -358,6 +358,13 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
358
358
|
});
|
|
359
359
|
authenticated.get("/api/sessions/:key/agent-config", async (c) => {
|
|
360
360
|
const key = c.req.param("key");
|
|
361
|
+
if (!await service.sessions.getSession(key)) return c.json({
|
|
362
|
+
ok: false,
|
|
363
|
+
error: {
|
|
364
|
+
code: "NOT_FOUND",
|
|
365
|
+
message: "Session not found"
|
|
366
|
+
}
|
|
367
|
+
}, 404);
|
|
361
368
|
const payload = await service.sessions.getFixedAgentConfig(key);
|
|
362
369
|
return c.json({
|
|
363
370
|
ok: true,
|
|
@@ -116,6 +116,19 @@ const RULE_STATUSES = new Set([
|
|
|
116
116
|
"disabled",
|
|
117
117
|
"archived"
|
|
118
118
|
]);
|
|
119
|
+
const MOBILE_PROFILE_PREDICATES = new Set([
|
|
120
|
+
"identity.call_name",
|
|
121
|
+
"identity.role",
|
|
122
|
+
"identity.pronouns",
|
|
123
|
+
"preference.timezone",
|
|
124
|
+
"preference.locale"
|
|
125
|
+
]);
|
|
126
|
+
const MOBILE_ASSERTION_FILTERS = new Set([
|
|
127
|
+
"all",
|
|
128
|
+
"explicit",
|
|
129
|
+
"learned",
|
|
130
|
+
"review"
|
|
131
|
+
]);
|
|
119
132
|
function assertionView(assertion, sources = listUserAssertionSources([assertion.id]).get(assertion.id) ?? []) {
|
|
120
133
|
const slot = getAssertionSlot(assertion.slotId);
|
|
121
134
|
if (!slot) throw new Error(`Assertion slot not found: ${assertion.slotId}`);
|
|
@@ -131,6 +144,70 @@ function assertionView(assertion, sources = listUserAssertionSources([assertion.
|
|
|
131
144
|
})
|
|
132
145
|
};
|
|
133
146
|
}
|
|
147
|
+
function mobileAssertionView(assertion, sources = listUserAssertionSources([assertion.id]).get(assertion.id) ?? []) {
|
|
148
|
+
const view = assertionView(assertion, sources);
|
|
149
|
+
return {
|
|
150
|
+
id: view.id,
|
|
151
|
+
predicate: view.predicate,
|
|
152
|
+
statement: view.statement,
|
|
153
|
+
kind: view.kind,
|
|
154
|
+
status: view.status,
|
|
155
|
+
authority: view.authority,
|
|
156
|
+
usable: view.usable,
|
|
157
|
+
confidence: view.confidence,
|
|
158
|
+
volatility: view.volatility,
|
|
159
|
+
layer: view.layer,
|
|
160
|
+
independentSourceCount: view.independentSourceCount,
|
|
161
|
+
observedAt: view.observedAt,
|
|
162
|
+
recordedAt: view.recordedAt,
|
|
163
|
+
...view.validTo === void 0 ? {} : { validTo: view.validTo },
|
|
164
|
+
scope: view.scope,
|
|
165
|
+
sources: view.sources
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function isMobileAssertion(item, filter) {
|
|
169
|
+
if (item.scope.type !== "global" || MOBILE_PROFILE_PREDICATES.has(item.predicate)) return false;
|
|
170
|
+
if (filter === "review") return item.status === "needs_review" || item.status === "conflicted";
|
|
171
|
+
if (!item.usable) return false;
|
|
172
|
+
if (filter === "explicit") return item.authority === "user_explicit";
|
|
173
|
+
if (filter === "learned") return item.authority !== "user_explicit";
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
function normalizeMobileSearch(value, maxLength) {
|
|
177
|
+
const normalized = (value ?? "").normalize("NFKC").trim().toLocaleLowerCase();
|
|
178
|
+
return maxLength === void 0 ? normalized : normalized.slice(0, maxLength);
|
|
179
|
+
}
|
|
180
|
+
function matchesMobileSearch(item, query) {
|
|
181
|
+
if (!query) return true;
|
|
182
|
+
const statusAliases = item.status === "needs_review" || item.status === "conflicted" ? "needs review review 待确认 需要确认" : item.status;
|
|
183
|
+
const authorityAliases = item.authority === "user_explicit" ? "explicit user said 你明确说过 用户明确" : "learned inferred 逐渐学到 系统推断";
|
|
184
|
+
return normalizeMobileSearch([
|
|
185
|
+
item.statement,
|
|
186
|
+
item.predicate,
|
|
187
|
+
item.kind,
|
|
188
|
+
statusAliases,
|
|
189
|
+
authorityAliases,
|
|
190
|
+
item.scope.type,
|
|
191
|
+
item.scope.id ?? "",
|
|
192
|
+
...item.sources.flatMap((source) => [
|
|
193
|
+
source.label ?? "",
|
|
194
|
+
source.kind,
|
|
195
|
+
source.category ?? ""
|
|
196
|
+
])
|
|
197
|
+
].join(" ")).includes(query);
|
|
198
|
+
}
|
|
199
|
+
function encodeMobileCursor(item) {
|
|
200
|
+
return Buffer.from(JSON.stringify([item.recordedAt, item.id])).toString("base64url");
|
|
201
|
+
}
|
|
202
|
+
function decodeMobileCursor(value) {
|
|
203
|
+
if (!value) return void 0;
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
206
|
+
return Array.isArray(parsed) && typeof parsed[0] === "number" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : void 0;
|
|
207
|
+
} catch {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
134
211
|
function registerUserModelRoutes(authenticated, deps) {
|
|
135
212
|
const write = deps.strictRateLimitMiddleware;
|
|
136
213
|
authenticated.get("/api/user-model", (c) => {
|
|
@@ -184,6 +261,78 @@ function registerUserModelRoutes(authenticated, deps) {
|
|
|
184
261
|
}
|
|
185
262
|
});
|
|
186
263
|
});
|
|
264
|
+
authenticated.get("/api/user-model/mobile-summary", (c) => {
|
|
265
|
+
const rawAssertions = listUserAssertions({
|
|
266
|
+
statuses: [
|
|
267
|
+
"active",
|
|
268
|
+
"candidate",
|
|
269
|
+
"needs_review",
|
|
270
|
+
"conflicted",
|
|
271
|
+
"stale"
|
|
272
|
+
],
|
|
273
|
+
limit: 2e3
|
|
274
|
+
});
|
|
275
|
+
const sourceMap = listUserAssertionSources(rawAssertions.map((item) => item.id));
|
|
276
|
+
const items = rawAssertions.map((item) => mobileAssertionView(item, sourceMap.get(item.id) ?? []));
|
|
277
|
+
const visible = items.filter((item) => isMobileAssertion(item, "all"));
|
|
278
|
+
const review = items.filter((item) => isMobileAssertion(item, "review"));
|
|
279
|
+
const profile = getUserProfileSnapshot();
|
|
280
|
+
const goals = listUserGoals();
|
|
281
|
+
const now = Date.now();
|
|
282
|
+
const primary = listPriorityWindows().filter((item) => item.status === "active" && item.rank === "primary" && item.validTo >= now).sort((left, right) => (right.declaredImportance ?? right.urgency) - (left.declaredImportance ?? left.urgency))[0];
|
|
283
|
+
const primaryGoal = primary?.targetType === "goal" ? goals.find((goal) => goal.id === primary.targetId) : void 0;
|
|
284
|
+
const primaryTitle = primaryGoal?.title ?? (primary && !/^[0-9a-f]{8}-[0-9a-f-]{20,}$/i.test(primary.targetId) ? primary.targetId : void 0);
|
|
285
|
+
const mobileGoals = goals.filter((goal) => goal.status === "active" || goal.status === "paused" || goal.status === "proposed").sort((left, right) => {
|
|
286
|
+
if (left.id === primaryGoal?.id) return -1;
|
|
287
|
+
if (right.id === primaryGoal?.id) return 1;
|
|
288
|
+
if (left.status === "active" && right.status !== "active") return -1;
|
|
289
|
+
if (right.status === "active" && left.status !== "active") return 1;
|
|
290
|
+
return (left.targetAt ?? Number.MAX_SAFE_INTEGER) - (right.targetAt ?? Number.MAX_SAFE_INTEGER) || right.updatedAt - left.updatedAt;
|
|
291
|
+
}).slice(0, 5).map((goal) => ({
|
|
292
|
+
id: goal.id,
|
|
293
|
+
title: goal.title,
|
|
294
|
+
desiredOutcome: goal.desiredOutcome,
|
|
295
|
+
status: goal.status,
|
|
296
|
+
...goal.targetAt === void 0 ? {} : { targetAt: goal.targetAt },
|
|
297
|
+
updatedAt: goal.updatedAt,
|
|
298
|
+
isPrimary: goal.id === primaryGoal?.id
|
|
299
|
+
}));
|
|
300
|
+
const result = {
|
|
301
|
+
profile: {
|
|
302
|
+
callName: profile.callName ?? "",
|
|
303
|
+
role: profile.role ?? "",
|
|
304
|
+
pronouns: profile.pronouns ?? "",
|
|
305
|
+
timezone: profile.timezone ?? "",
|
|
306
|
+
locale: profile.locale ?? ""
|
|
307
|
+
},
|
|
308
|
+
suggestedCallName: profile.callName || machineCallName(),
|
|
309
|
+
counts: {
|
|
310
|
+
total: visible.length,
|
|
311
|
+
explicit: visible.filter((item) => item.authority === "user_explicit").length,
|
|
312
|
+
learned: visible.filter((item) => item.authority !== "user_explicit").length,
|
|
313
|
+
review: review.length,
|
|
314
|
+
workMemory: listKnowledgeItems({
|
|
315
|
+
statuses: ["active"],
|
|
316
|
+
recordClass: "memory",
|
|
317
|
+
limit: 2e3
|
|
318
|
+
}).length
|
|
319
|
+
},
|
|
320
|
+
...primary && primaryTitle ? { primaryFocus: {
|
|
321
|
+
id: primary.id,
|
|
322
|
+
title: primaryTitle,
|
|
323
|
+
...primaryGoal?.desiredOutcome ? { desiredOutcome: primaryGoal.desiredOutcome } : {},
|
|
324
|
+
validTo: primary.validTo
|
|
325
|
+
} } : {},
|
|
326
|
+
goals: mobileGoals,
|
|
327
|
+
recent: [...visible].sort((left, right) => right.recordedAt - left.recordedAt).slice(0, 3),
|
|
328
|
+
rules: listCollaborationRules().filter((rule) => rule.status === "active").slice(0, 3).map((rule) => ({
|
|
329
|
+
id: rule.id,
|
|
330
|
+
statement: rule.statement,
|
|
331
|
+
category: rule.category
|
|
332
|
+
}))
|
|
333
|
+
};
|
|
334
|
+
return c.json(result);
|
|
335
|
+
});
|
|
187
336
|
authenticated.patch("/api/user-model/profile", write, async (c) => {
|
|
188
337
|
const input = await body(c);
|
|
189
338
|
if (!input) return c.json({ error: "A profile patch is required" }, 400);
|
|
@@ -224,6 +373,34 @@ function registerUserModelRoutes(authenticated, deps) {
|
|
|
224
373
|
}
|
|
225
374
|
});
|
|
226
375
|
authenticated.get("/api/user-model/assertions", (c) => {
|
|
376
|
+
if (c.req.query("view") === "mobile") {
|
|
377
|
+
const filter = c.req.query("filter") ?? "all";
|
|
378
|
+
if (!MOBILE_ASSERTION_FILTERS.has(filter)) return c.json({ error: "Invalid mobile assertion filter" }, 400);
|
|
379
|
+
const requestedLimit = Number(c.req.query("limit") ?? 20);
|
|
380
|
+
const limit = Number.isFinite(requestedLimit) ? Math.max(1, Math.min(50, Math.trunc(requestedLimit))) : 20;
|
|
381
|
+
const query = normalizeMobileSearch(c.req.query("q"), 100);
|
|
382
|
+
const cursorValue = c.req.query("cursor");
|
|
383
|
+
const cursor = decodeMobileCursor(cursorValue);
|
|
384
|
+
if (cursorValue && !cursor) return c.json({ error: "Invalid cursor" }, 400);
|
|
385
|
+
const assertions = listUserAssertions({
|
|
386
|
+
statuses: [
|
|
387
|
+
"active",
|
|
388
|
+
"candidate",
|
|
389
|
+
"needs_review",
|
|
390
|
+
"conflicted",
|
|
391
|
+
"stale"
|
|
392
|
+
],
|
|
393
|
+
limit: 2e3
|
|
394
|
+
});
|
|
395
|
+
const sourceMap = listUserAssertionSources(assertions.map((item) => item.id));
|
|
396
|
+
const filtered = assertions.map((item) => mobileAssertionView(item, sourceMap.get(item.id) ?? [])).filter((item) => isMobileAssertion(item, filter)).filter((item) => matchesMobileSearch(item, query)).sort((left, right) => right.recordedAt - left.recordedAt || right.id.localeCompare(left.id)).filter((item) => !cursor || item.recordedAt < cursor[0] || item.recordedAt === cursor[0] && item.id.localeCompare(cursor[1]) < 0);
|
|
397
|
+
const items = filtered.slice(0, limit);
|
|
398
|
+
const result = {
|
|
399
|
+
items,
|
|
400
|
+
...filtered.length > limit && items.length ? { nextCursor: encodeMobileCursor(items[items.length - 1]) } : {}
|
|
401
|
+
};
|
|
402
|
+
return c.json(result);
|
|
403
|
+
}
|
|
227
404
|
const requested = c.req.query("status")?.split(",").filter(Boolean);
|
|
228
405
|
if (requested?.some((status) => !ASSERTION_STATUSES.has(status))) return c.json({ error: "Invalid assertion status" }, 400);
|
|
229
406
|
const assertions = listUserAssertions({
|
|
@@ -363,6 +540,31 @@ function registerUserModelRoutes(authenticated, deps) {
|
|
|
363
540
|
const goal = setUserGoalStatus(c.req.param("id"), status);
|
|
364
541
|
return goal ? c.json({ goal }) : c.json({ error: "Goal not found" }, 404);
|
|
365
542
|
});
|
|
543
|
+
authenticated.patch("/api/user-model/goals/:id", write, async (c) => {
|
|
544
|
+
const input = await body(c);
|
|
545
|
+
const current = listUserGoals().find((goal) => goal.id === c.req.param("id"));
|
|
546
|
+
if (!current) return c.json({ error: "Goal not found" }, 404);
|
|
547
|
+
if (!input) return c.json({ error: "A goal patch is required" }, 400);
|
|
548
|
+
const title = Object.hasOwn(input, "title") ? input.title : current.title;
|
|
549
|
+
const desiredOutcome = Object.hasOwn(input, "desiredOutcome") ? input.desiredOutcome : current.desiredOutcome;
|
|
550
|
+
const rawTargetAt = Object.hasOwn(input, "targetAt") ? input.targetAt : current.targetAt;
|
|
551
|
+
const status = Object.hasOwn(input, "status") ? input.status : current.status;
|
|
552
|
+
if (typeof title !== "string" || typeof desiredOutcome !== "string" || rawTargetAt !== void 0 && rawTargetAt !== null && typeof rawTargetAt !== "number" || typeof status !== "string" || !GOAL_STATUSES.has(status)) return c.json({ error: "Goal patch fields have invalid types" }, 400);
|
|
553
|
+
const targetAt = typeof rawTargetAt === "number" ? rawTargetAt : rawTargetAt === null ? null : void 0;
|
|
554
|
+
try {
|
|
555
|
+
const goal = runSqliteWriteTransaction(() => {
|
|
556
|
+
const updated = updateUserGoal(current.id, {
|
|
557
|
+
title,
|
|
558
|
+
desiredOutcome,
|
|
559
|
+
...targetAt === void 0 ? {} : { targetAt }
|
|
560
|
+
});
|
|
561
|
+
return status === current.status ? updated : setUserGoalStatus(current.id, status);
|
|
562
|
+
});
|
|
563
|
+
return c.json({ goal });
|
|
564
|
+
} catch (error) {
|
|
565
|
+
return c.json({ error: errorMessage(error) }, 400);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
366
568
|
authenticated.get("/api/user-model/rules", (c) => c.json({ rules: listCollaborationRules() }));
|
|
367
569
|
authenticated.post("/api/user-model/rules", write, async (c) => {
|
|
368
570
|
const input = await body(c);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { acquireGatewayLock } from "./lock.js";
|
|
2
2
|
import { loadConfig } from "../config/loader.js";
|
|
3
|
-
import { runBootstrapMigrationsSync } from "../migrations/runner.js";
|
|
4
3
|
import "../config/index.js";
|
|
4
|
+
import { runBootstrapMigrationsSync } from "../migrations/runner.js";
|
|
5
5
|
import { isRestartEnabled } from "../config/commands.flags.js";
|
|
6
6
|
import { restartGatewayProcessWithFreshPid } from "./respawn.js";
|
|
7
7
|
import { consumeGatewayRestartIntentSync, consumeGatewaySigusr1RestartAuthorization, isGatewaySigusr1RestartExternallyAllowed, resetGatewayRestartStateForInProcessRestart, scheduleGatewaySigusr1Restart, setGatewaySigusr1RestartPolicy } from "../infra/restart.js";
|
|
@@ -35,6 +35,9 @@ function requiredGatewayScope(method, path) {
|
|
|
35
35
|
if (path === "/api/voice/selection" || path === "/api/voice/catalog/refresh") return "voice.configure";
|
|
36
36
|
if (path.startsWith("/api/voice") || path.startsWith("/api/media") || path.startsWith("/api/clarifications")) return "sessions.write";
|
|
37
37
|
if (path.startsWith("/api/commands") || path.startsWith("/api/skills")) return methodScope(method, "agents.read", "gateway.admin");
|
|
38
|
+
if (path === "/api/user-model/refresh" || path.startsWith("/api/user-model/refresh/")) return "gateway.admin";
|
|
39
|
+
if (path === "/api/user-model" || path.startsWith("/api/user-model/")) return methodScope(method, "workspace.read", "workspace.write");
|
|
40
|
+
if (path === "/api/knowledge-memory" || path.startsWith("/api/knowledge-memory/")) return methodScope(method, "workspace.read", "workspace.write");
|
|
38
41
|
if (path === "/api/discussions" || path.startsWith("/api/discussions/") || path === "/api/discussion-capture/settings" || path.startsWith("/api/workspace") || path.startsWith("/api/files") || path.startsWith("/api/projects") || path.startsWith("/api/notes") || path.startsWith("/api/shares")) return methodScope(method, "workspace.read", "workspace.write");
|
|
39
42
|
return "gateway.admin";
|
|
40
43
|
}
|
|
@@ -26,7 +26,7 @@ function sameAppContext(input, existing) {
|
|
|
26
26
|
return isDeepStrictEqual(identity(input.sourceContexts), identity(existing.contextSnapshots));
|
|
27
27
|
}
|
|
28
28
|
function contextRefsMatchFrozenSnapshot(requested, frozen) {
|
|
29
|
-
const editable = frozen?.filter((ref) => ref.kind === "note" || ref.kind === "task" || ref.kind === "file" || ref.kind === "session" || ref.kind === "browser_tab" || ref.kind === "mcp_resource") ?? [];
|
|
29
|
+
const editable = frozen?.filter((ref) => ref.kind === "note" || ref.kind === "task" || ref.kind === "file" || ref.kind === "session" || ref.kind === "browser_tab" || ref.kind === "mcp_resource" || ref.kind === "user_assertion") ?? [];
|
|
30
30
|
if (requested.length !== editable.length) return false;
|
|
31
31
|
return requested.every((ref, index) => {
|
|
32
32
|
const snapshot = editable[index];
|
|
@@ -65,7 +65,6 @@ import { MessageBus, MessageBusShutdownError } from "../infra/bus/queue.js";
|
|
|
65
65
|
import "../infra/bus/index.js";
|
|
66
66
|
import { collectMediaUrisFromMessages, deleteMediaUris } from "../media/session-references.js";
|
|
67
67
|
import { AgentService } from "../agent/service.js";
|
|
68
|
-
import { bootstrapApplicationStateSync } from "../bootstrap/application-state.js";
|
|
69
68
|
import { setPairingBroadcastSink } from "../channels/pairing/pairing-events.js";
|
|
70
69
|
import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
|
|
71
70
|
import { ChannelManager } from "../channels/manager.js";
|
|
@@ -73,6 +72,7 @@ import { ChatPreviewService } from "../chat-previews/service.js";
|
|
|
73
72
|
import "../chat-previews/index.js";
|
|
74
73
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
75
74
|
import "../config/index.js";
|
|
75
|
+
import { bootstrapApplicationStateSync } from "../bootstrap/application-state.js";
|
|
76
76
|
import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
|
|
77
77
|
import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
|
|
78
78
|
import "../knowledge/index.js";
|
|
@@ -98,6 +98,7 @@ import { buildFileAgentContext } from "../agent/source-context/file-context.js";
|
|
|
98
98
|
import { buildSessionAgentContext } from "../agent/source-context/session-context.js";
|
|
99
99
|
import { buildMcpResourceAgentContext } from "../agent/source-context/mcp-resource-context.js";
|
|
100
100
|
import { buildBrowserTabAgentContext } from "../agent/source-context/browser-tab.js";
|
|
101
|
+
import { buildUserAssertionAgentContext } from "../agent/source-context/user-assertion-context.js";
|
|
101
102
|
import { WorkDiscoveryService } from "../work-discovery/service.js";
|
|
102
103
|
import { buildVoiceMemoryContext } from "../voice/realtime/memory-context.js";
|
|
103
104
|
import { buildVoicePersonaContext } from "../voice/realtime/persona-context.js";
|
|
@@ -504,6 +505,10 @@ var GatewayService = class {
|
|
|
504
505
|
getConfig: () => this.config,
|
|
505
506
|
resolveTurnContext: async (ref, conversationId) => {
|
|
506
507
|
if (ref.kind === "task") return buildTaskAgentContext(new TaskRepository().get(ref.sourceId), ref.expectedVersion);
|
|
508
|
+
if (ref.kind === "user_assertion") {
|
|
509
|
+
const metadata = await this.sessionIndex.getSessionMetadata(conversationId);
|
|
510
|
+
return buildUserAssertionAgentContext(ref.sourceId, ref.expectedVersion, metadata?.agentId);
|
|
511
|
+
}
|
|
507
512
|
if (ref.kind === "file") {
|
|
508
513
|
const files = getGatewayFileSpaceService(this);
|
|
509
514
|
const space = await files.forContext("session", conversationId).catch(() => null);
|
|
@@ -50,7 +50,7 @@ export declare function setUserGoalStatus(id: string, status: UserGoalStatus, no
|
|
|
50
50
|
export declare function updateUserGoal(id: string, input: {
|
|
51
51
|
title: string;
|
|
52
52
|
desiredOutcome: string;
|
|
53
|
-
targetAt?: number;
|
|
53
|
+
targetAt?: number | null;
|
|
54
54
|
}, now?: number): UserGoal | undefined;
|
|
55
55
|
export declare function listPriorityWindows(principalId?: string): UserPriorityWindow[];
|
|
56
56
|
export declare function createPriorityWindow(input: {
|
|
@@ -65,8 +65,9 @@ function updateUserGoal(id, input, now = Date.now()) {
|
|
|
65
65
|
db.prepare(`INSERT INTO user_goal_revisions (
|
|
66
66
|
revision_id, goal_id, title, desired_outcome, created_by, change_reason, created_at
|
|
67
67
|
) VALUES (?, ?, ?, ?, 'user', 'Goal edited by user.', ?)`).run(revisionId, id, title, desiredOutcome, now);
|
|
68
|
+
const targetAt = input.targetAt === void 0 ? current.targetAt ?? null : input.targetAt;
|
|
68
69
|
db.prepare(`UPDATE user_goals SET current_revision_id = ?, target_at = ?, updated_at = ?
|
|
69
|
-
WHERE goal_id = ?`).run(revisionId,
|
|
70
|
+
WHERE goal_id = ?`).run(revisionId, targetAt, now, id);
|
|
70
71
|
});
|
|
71
72
|
return listUserGoals().find((goal) => goal.id === id);
|
|
72
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.338",
|
|
4
4
|
"description": "Local-first personal AI for the one-person company, with durable context, tasks, workflows, automations, and local or cloud models.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -159,11 +159,11 @@
|
|
|
159
159
|
"vitest": "4.1.5",
|
|
160
160
|
"vue": "^3.5.35",
|
|
161
161
|
"@xopcai/browser-control-contract": "0.1.0",
|
|
162
|
-
"@xopcai/endpoint-tools-client": "0.0.0",
|
|
163
162
|
"@xopcai/computer-control-contract": "0.1.0",
|
|
163
|
+
"@xopcai/endpoint-tools-client": "0.0.0",
|
|
164
164
|
"@xopcai/endpoint-tools-protocol": "0.0.0",
|
|
165
|
-
"@xopcai/realtime-client": "0.0.0",
|
|
166
165
|
"@xopcai/gateway-contract": "0.0.0",
|
|
166
|
+
"@xopcai/realtime-client": "0.0.0",
|
|
167
167
|
"@xopcai/realtime-protocol": "0.0.0"
|
|
168
168
|
},
|
|
169
169
|
"scripts": {
|