@notis_ai/cli 0.2.0-beta.19.1 → 0.2.0-beta.196.1
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/README.md +822 -135
- package/bin/check-runtime.js +15 -0
- package/bin/notis.js +2 -0
- package/config/notis_app_boundary_rules.json +50 -0
- package/config/notis_app_design_rules.json +135 -0
- package/config/portal-route-roots.json +48 -0
- package/dist/agent-hooks/notis-agent-hook.mjs +45587 -0
- package/dist/base-skills/notis-apps/SKILL.md +93 -0
- package/dist/base-skills/notis-apps/references/architecture.md +114 -0
- package/dist/base-skills/notis-apps/references/context.md +81 -0
- package/dist/base-skills/notis-apps/references/design.md +97 -0
- package/dist/base-skills/notis-apps/references/memory.md +58 -0
- package/dist/base-skills/notis-apps/references/reading.md +67 -0
- package/dist/base-skills/notis-apps/references/release.md +107 -0
- package/dist/base-skills/notis-apps/references/sdk.md +116 -0
- package/dist/base-skills/notis-apps/references/troubleshooting.md +24 -0
- package/dist/base-skills/notis-apps/references/views.md +142 -0
- package/dist/base-skills/notis-cli/SKILL.md +154 -0
- package/dist/base-skills/notis-cli/references/app-delivery.md +19 -0
- package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
- package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
- package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
- package/dist/base-skills/notis-cli/references/troubleshooting.md +39 -0
- package/dist/base-skills/notis-query/SKILL.md +41 -0
- package/dist/base-skills/notis-query/references/database-discovery.md +60 -0
- package/dist/base-skills/notis-query/references/documents.md +63 -0
- package/dist/base-skills/notis-query/references/query.md +76 -0
- package/{template/packages/notis-sdk → dist/sdk}/package.json +14 -4
- package/dist/sdk/src/agentContext.ts +36 -0
- package/dist/sdk/src/bundleModule.ts +79 -0
- package/dist/sdk/src/components/Dialog.tsx +46 -0
- package/dist/sdk/src/components/DocumentEditor.tsx +106 -0
- package/dist/sdk/src/components/DocumentPage.tsx +141 -0
- package/dist/sdk/src/components/Markdown.tsx +60 -0
- package/dist/sdk/src/components/MarkdownEditor.tsx +121 -0
- package/dist/sdk/src/components/MultiSelectActionBar.tsx +285 -0
- package/dist/sdk/src/components/MultiSelectCheckbox.tsx +97 -0
- package/dist/sdk/src/components/MultiSelectDragOverlay.tsx +39 -0
- package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
- package/dist/sdk/src/components/NotisSelectionBoundary.tsx +59 -0
- package/dist/sdk/src/components/RecordComponents.tsx +33 -0
- package/dist/sdk/src/components/RenderChartData.tsx +19 -0
- package/dist/sdk/src/components/ShortcutHints.tsx +56 -0
- package/dist/sdk/src/components/Skeleton.tsx +24 -0
- package/dist/sdk/src/config.ts +239 -0
- package/dist/sdk/src/documents.ts +258 -0
- package/dist/sdk/src/hooks/useAction.ts +28 -0
- package/dist/sdk/src/hooks/useActiveResource.ts +19 -0
- package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
- package/dist/sdk/src/hooks/useCloudComputer.ts +95 -0
- package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
- package/dist/sdk/src/hooks/useCollectionInteractions.ts +838 -0
- package/dist/sdk/src/hooks/useDatabaseSchema.ts +49 -0
- package/dist/sdk/src/hooks/useDatabaseSubscription.ts +76 -0
- package/dist/sdk/src/hooks/useDocument.ts +43 -0
- package/dist/sdk/src/hooks/useDocuments.ts +84 -0
- package/dist/sdk/src/hooks/useHandover.ts +78 -0
- package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
- package/dist/sdk/src/hooks/useMultiSelect.ts +95 -0
- package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
- package/dist/sdk/src/hooks/useNativeDocuments.ts +83 -0
- package/dist/sdk/src/hooks/useNotis.ts +42 -0
- package/dist/sdk/src/hooks/useNotisNavigation.ts +67 -0
- package/dist/sdk/src/hooks/useQuery.ts +74 -0
- package/dist/sdk/src/hooks/useTool.ts +65 -0
- package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
- package/dist/sdk/src/hooks/useTopBarSearch.ts +81 -0
- package/dist/sdk/src/hooks/useUpsertDocument.ts +95 -0
- package/dist/sdk/src/hooks/useViewParams.ts +121 -0
- package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
- package/dist/sdk/src/index.ts +200 -0
- package/dist/sdk/src/interactions/actions.ts +59 -0
- package/dist/sdk/src/interactions/shortcuts.tsx +740 -0
- package/dist/sdk/src/interactions/visibility.ts +13 -0
- package/dist/sdk/src/interactions.ts +45 -0
- package/dist/sdk/src/nativeData.ts +39 -0
- package/dist/sdk/src/presentation.tsx +82 -0
- package/dist/sdk/src/provider.tsx +49 -0
- package/dist/sdk/src/queryCache.ts +172 -0
- package/dist/sdk/src/queryErrors.ts +51 -0
- package/dist/sdk/src/runtime.ts +603 -0
- package/dist/sdk/src/space.ts +425 -0
- package/dist/sdk/src/styles.css +290 -0
- package/dist/sdk/src/tailwind.ts +66 -0
- package/dist/sdk/src/vite.ts +83 -0
- package/dist/skill-sync/index.js +2143 -0
- package/dist/skill-sync/index.js.map +7 -0
- package/dist/skill-sync-worker.mjs +3487 -0
- package/dist/space-harness/host.js +66 -0
- package/dist/view-renderer/dist/host.css +1 -0
- package/dist/view-renderer/dist/host.js +1042 -0
- package/dist/view-renderer/dist/theme.css +73 -0
- package/dist/view-renderer/src/dom.js +180 -0
- package/dist/view-renderer/src/errors.js +8 -0
- package/dist/view-renderer/src/host.tsx +173 -0
- package/dist/view-renderer/src/index.js +4 -0
- package/dist/view-renderer/src/pool.js +76 -0
- package/dist/view-renderer/src/remote-broker.js +59 -0
- package/dist/view-renderer/src/renderer.js +201 -0
- package/package.json +25 -8
- package/skills/notis-apps/cli.md +406 -0
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
- package/skills/notis-onboarding/BRIEF.md +133 -0
- package/skills/notis-query/cli.md +39 -0
- package/src/agent-hook-entry.js +5 -0
- package/src/cli.js +294 -25
- package/src/command-specs/agents.js +392 -0
- package/src/command-specs/apps.js +1476 -203
- package/src/command-specs/auth.js +114 -137
- package/src/command-specs/diagnostics.js +730 -0
- package/src/command-specs/files.js +29 -0
- package/src/command-specs/handover.js +374 -0
- package/src/command-specs/helpers.js +86 -82
- package/src/command-specs/index.js +31 -6
- package/src/command-specs/meta.js +150 -18
- package/src/command-specs/onboarding.js +290 -0
- package/src/command-specs/profile.js +358 -0
- package/src/command-specs/skills.js +304 -0
- package/src/command-specs/smoke.js +386 -0
- package/src/command-specs/spaces.js +572 -0
- package/src/command-specs/tools.js +455 -139
- package/src/command-specs/views.js +69 -0
- package/src/runtime/agent-browser.js +700 -0
- package/src/runtime/agent-memory-state.js +126 -0
- package/src/runtime/agent-setup.js +383 -0
- package/src/runtime/app-boundary-validator.js +407 -0
- package/src/runtime/app-changelog.js +79 -0
- package/src/runtime/app-data-literals.js +82 -0
- package/src/runtime/app-platform.js +2752 -237
- package/src/runtime/app-registry-scaffolds.js +367 -0
- package/src/runtime/app-test-server.js +293 -0
- package/src/runtime/assets/store-screenshot-dark.png +0 -0
- package/src/runtime/auth-recovery.js +110 -0
- package/src/runtime/base-skills.d.ts +20 -0
- package/src/runtime/base-skills.js +167 -0
- package/src/runtime/channel.js +133 -0
- package/src/runtime/confined-space-build.js +74 -0
- package/src/runtime/confined-space-verify.js +49 -0
- package/src/runtime/delegated-context.js +68 -0
- package/src/runtime/errors.js +1 -0
- package/src/runtime/git.js +233 -0
- package/src/runtime/login-listener.js +15 -0
- package/src/runtime/native-record-files.js +47 -0
- package/src/runtime/oauth.js +2622 -0
- package/src/runtime/output.js +37 -5
- package/src/runtime/ports.js +31 -0
- package/src/runtime/profiles.js +906 -55
- package/src/runtime/retired-sdk-files.js +20 -0
- package/src/runtime/screenshot-framing.js +85 -0
- package/src/runtime/skill-sync/cloud-client.ts +121 -0
- package/src/runtime/skill-sync/index.ts +905 -0
- package/src/runtime/skill-sync/local-scanner.ts +1259 -0
- package/src/runtime/skill-sync/native-identity.ts +102 -0
- package/src/runtime/skill-sync/native-plan.ts +59 -0
- package/src/runtime/skill-sync/symlink-manager.ts +433 -0
- package/src/runtime/skill-sync/sync-plan.ts +54 -0
- package/src/runtime/skill-sync/types.ts +157 -0
- package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
- package/src/runtime/skill-sync-service.js +109 -0
- package/src/runtime/source-root.js +32 -0
- package/src/runtime/space-collection-scaffold.js +66 -0
- package/src/runtime/space-database-structures.js +229 -0
- package/src/runtime/space-fixture-broker.js +50 -0
- package/src/runtime/space-lock.js +337 -0
- package/src/runtime/space-platform.js +105 -0
- package/src/runtime/space-source.js +281 -0
- package/src/runtime/space-test-server.js +327 -0
- package/src/runtime/space-verification.js +89 -0
- package/src/runtime/space-verify-browser-worker.js +51 -0
- package/src/runtime/space-view-manifest.js +254 -0
- package/src/runtime/store-screenshot.js +146 -0
- package/src/runtime/sync-skills.d.ts +37 -0
- package/src/runtime/sync-skills.js +231 -0
- package/src/runtime/telemetry.js +92 -0
- package/src/runtime/transport.js +331 -45
- package/src/runtime/view-render.js +49 -0
- package/src/skill-sync-worker-entry.js +2 -0
- package/src/skill-sync-worker.js +50 -0
- package/src/space-harness-host.ts +103 -0
- package/template/.harness/index.html.tmpl +435 -0
- package/template/CHANGELOG.md +5 -0
- package/template/app/globals.css +29 -3
- package/template/app/layout.tsx +6 -3
- package/template/app/page.tsx +49 -42
- package/template/components/page-heading.tsx +23 -0
- package/template/components/ui/badge.tsx +7 -4
- package/template/components/ui/button.tsx +1 -1
- package/template/components/ui/card.tsx +24 -11
- package/template/components/ui/native-select.tsx +24 -0
- package/template/notis.config.ts +24 -6
- package/template/package-lock.json +3642 -0
- package/template/package.json +19 -16
- package/template/postcss.config.mjs +1 -1
- package/template/tailwind.config.ts +1 -6
- package/template/tsconfig.json +1 -0
- package/src/command-specs/db.js +0 -163
- package/src/runtime/app-preview-server.js +0 -312
- package/template/packages/notis-sdk/src/config.ts +0 -48
- package/template/packages/notis-sdk/src/helpers.ts +0 -131
- package/template/packages/notis-sdk/src/hooks/useAppState.ts +0 -50
- package/template/packages/notis-sdk/src/hooks/useCollectionItem.ts +0 -58
- package/template/packages/notis-sdk/src/hooks/useDatabase.ts +0 -87
- package/template/packages/notis-sdk/src/hooks/useDocument.ts +0 -61
- package/template/packages/notis-sdk/src/hooks/useNotis.ts +0 -31
- package/template/packages/notis-sdk/src/hooks/useNotisNavigation.ts +0 -49
- package/template/packages/notis-sdk/src/hooks/useTool.ts +0 -49
- package/template/packages/notis-sdk/src/hooks/useUpsertDocument.ts +0 -57
- package/template/packages/notis-sdk/src/index.ts +0 -47
- package/template/packages/notis-sdk/src/provider.tsx +0 -44
- package/template/packages/notis-sdk/src/runtime.ts +0 -159
- package/template/packages/notis-sdk/src/styles.css +0 -123
- package/template/packages/notis-sdk/src/vite.ts +0 -54
- package/template/packages/notis-sdk/tsconfig.json +0 -15
- /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useBackend.ts +0 -0
- /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useTools.ts +0 -0
- /package/{template/packages/notis-sdk → dist/sdk}/src/ui.ts +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Exact canonical files retired by the one-Shadow-runtime cutover.
|
|
2
|
+
* Modified or additional source is retained for explicit reconciliation. */
|
|
3
|
+
// Host mounting code stays in the canonical SDK and CLI host bundle, not in
|
|
4
|
+
// authored apps' public SDK mirror. It is not a public package export.
|
|
5
|
+
export const HOST_ONLY_SDK_FILES = Object.freeze(['src/presentation.tsx']);
|
|
6
|
+
|
|
7
|
+
export const RETIRED_SDK_FILES = Object.freeze({
|
|
8
|
+
"src/presentation.tsx": [
|
|
9
|
+
"d29022f92e1e96b451b62cc8a561878a1c0cf8a3b4c0419181de7266f8a1b525"
|
|
10
|
+
],
|
|
11
|
+
"src/isolatedHost.tsx": [
|
|
12
|
+
"7f59049281a9533d39c557ca75635073c2f404f1eb0a528b274323d61db776cd"
|
|
13
|
+
],
|
|
14
|
+
"src/frameProtocol.ts": [
|
|
15
|
+
"f32337ddb507718be04289a4acf50cf2485698bc716556230f35f06a6f633f19"
|
|
16
|
+
],
|
|
17
|
+
"src/frameIsolation.ts": [
|
|
18
|
+
"8b57cb38f618eefc4133ae50fbf2b37bbdef5be02e44b39758d8328fb2a59ab6"
|
|
19
|
+
]
|
|
20
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Runs only in the capture harness, never in an installed app. */
|
|
2
|
+
export function measureScreenshotContent() {
|
|
3
|
+
const root = document.getElementById('root');
|
|
4
|
+
if (!root) return null;
|
|
5
|
+
const viewportWidth = document.documentElement.clientWidth;
|
|
6
|
+
const visible = (element) => {
|
|
7
|
+
const rect = element.getBoundingClientRect();
|
|
8
|
+
const style = getComputedStyle(element);
|
|
9
|
+
return rect.width > 0 && rect.height > 0
|
|
10
|
+
&& style.display !== 'none' && style.visibility !== 'hidden';
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Follow layout wrappers only while they contain the entire visible app.
|
|
14
|
+
// Never select one column, card, or control out of a multi-pane layout.
|
|
15
|
+
let node = root;
|
|
16
|
+
let content = null;
|
|
17
|
+
while (node) {
|
|
18
|
+
const hasOwnText = Array.from(node.childNodes).some(
|
|
19
|
+
(child) => child.nodeType === 3 && child.textContent.trim(),
|
|
20
|
+
);
|
|
21
|
+
const children = Array.from(node.children).filter(visible);
|
|
22
|
+
if (hasOwnText || children.length !== 1) break;
|
|
23
|
+
node = children[0];
|
|
24
|
+
const rect = node.getBoundingClientRect();
|
|
25
|
+
if (['DIV', 'MAIN', 'SECTION', 'ARTICLE', 'FORM'].includes(node.tagName)
|
|
26
|
+
&& rect.width >= 320 && rect.height >= 160
|
|
27
|
+
&& rect.width < viewportWidth * 0.9) {
|
|
28
|
+
content = node;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!content) return null;
|
|
32
|
+
content.setAttribute('data-notis-screenshot-content', '');
|
|
33
|
+
const rect = content.getBoundingClientRect();
|
|
34
|
+
return {
|
|
35
|
+
selector: '[data-notis-screenshot-content]',
|
|
36
|
+
width: rect.width,
|
|
37
|
+
height: rect.height,
|
|
38
|
+
viewport_width: viewportWidth,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const MEASURE_SCREENSHOT_CONTENT_SCRIPT = `(${measureScreenshotContent.toString()})()`;
|
|
43
|
+
|
|
44
|
+
/** Keep long pages readable, and rasterize bounded views at their final width. */
|
|
45
|
+
export function contentCapturePlan(bounds, viewport, outputWidth, outputHeight) {
|
|
46
|
+
const aspect = outputWidth / outputHeight;
|
|
47
|
+
if (bounds.width / bounds.height < aspect * 0.75) {
|
|
48
|
+
const width = Math.max(768, Math.ceil((bounds.width + 32) / 8) * 8);
|
|
49
|
+
return { focus: false, width, height: Math.round(width / aspect), scale: outputWidth / width };
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
focus: true,
|
|
53
|
+
width: viewport.width,
|
|
54
|
+
height: viewport.height,
|
|
55
|
+
scale: Math.min(4, outputWidth / bounds.width),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function safeViewportHeight(rectangles, height) {
|
|
60
|
+
const crossing = rectangles.filter((rect) => rect.top < height && rect.bottom > height
|
|
61
|
+
&& rect.top >= height * 0.85);
|
|
62
|
+
return crossing.length
|
|
63
|
+
? Math.max(Math.ceil(height * 0.85), Math.floor(Math.min(...crossing.map((rect) => rect.top)) - 8))
|
|
64
|
+
: height;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// End a long-page viewport in whitespace rather than through a text line or
|
|
68
|
+
// control. Only geometry leaves the browser; no page text is returned.
|
|
69
|
+
export const SAFE_VIEWPORT_HEIGHT_SCRIPT = `(() => {
|
|
70
|
+
const root = document.getElementById('root');
|
|
71
|
+
if (!root) return innerHeight;
|
|
72
|
+
const rects = [];
|
|
73
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
74
|
+
let node;
|
|
75
|
+
while ((node = walker.nextNode())) {
|
|
76
|
+
if (!node.textContent.trim() || getComputedStyle(node.parentElement).visibility !== 'visible') continue;
|
|
77
|
+
const range = document.createRange(); range.selectNodeContents(node);
|
|
78
|
+
for (const rect of range.getClientRects()) rects.push({ top: rect.top, bottom: rect.bottom });
|
|
79
|
+
}
|
|
80
|
+
for (const control of root.querySelectorAll('button,input,select,textarea')) {
|
|
81
|
+
const rect = control.getBoundingClientRect();
|
|
82
|
+
rects.push({ top: rect.top, bottom: rect.bottom });
|
|
83
|
+
}
|
|
84
|
+
return (${safeViewportHeight.toString()})(rects, innerHeight);
|
|
85
|
+
})()`;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { captureNativeSkillFiles, createSkillBundleBase64 } from './local-scanner';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { checkedNativeReference } from './native-identity';
|
|
4
|
+
import type { AgentTargets, LocalSkill, NativeSkillReference, SyncPullResponse, SyncPushResponse, SyncSettings } from './types';
|
|
5
|
+
|
|
6
|
+
type JsonBody = Record<string, unknown> | undefined;
|
|
7
|
+
|
|
8
|
+
async function requestJson<T>(
|
|
9
|
+
url: string,
|
|
10
|
+
jwt: string,
|
|
11
|
+
options: { method?: string; body?: JsonBody } = {},
|
|
12
|
+
): Promise<T> {
|
|
13
|
+
const response = await fetch(url, {
|
|
14
|
+
signal: AbortSignal.timeout(90_000),
|
|
15
|
+
method: options.method || 'POST',
|
|
16
|
+
headers: {
|
|
17
|
+
'Content-Type': 'application/json',
|
|
18
|
+
Authorization: `Bearer ${jwt}`,
|
|
19
|
+
},
|
|
20
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
const text = await response.text();
|
|
25
|
+
throw new Error(`${options.method || 'POST'} ${url} → ${response.status}: ${text}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return response.json() as Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function fetchSyncSettings(serverUrl: string, jwt: string): Promise<SyncSettings> {
|
|
32
|
+
return requestJson<SyncSettings>(`${serverUrl}/portal_skills/sync-settings`, jwt, {
|
|
33
|
+
body: {},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function pullSkills(serverUrl: string, jwt: string): Promise<SyncPullResponse> {
|
|
38
|
+
return requestJson<SyncPullResponse>(`${serverUrl}/portal_skills/sync-pull`, jwt, {
|
|
39
|
+
body: { skill_sync_protocol: 2 },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function pushChangedSkills(
|
|
44
|
+
serverUrl: string,
|
|
45
|
+
jwt: string,
|
|
46
|
+
changedSkills: LocalSkill[],
|
|
47
|
+
): Promise<SyncPushResponse> {
|
|
48
|
+
const payloadSkills = await Promise.all(changedSkills.map(async (skill) => ({
|
|
49
|
+
name: skill.name,
|
|
50
|
+
description: skill.description,
|
|
51
|
+
skill_md: skill.skillMd,
|
|
52
|
+
source_url: skill.sourceUrl,
|
|
53
|
+
folder_hash: skill.folderHash,
|
|
54
|
+
...(skill.nativeReference ? { bundle_files: await captureNativeSkillFiles(skill) }
|
|
55
|
+
: { bundle_base64: await createSkillBundleBase64(skill) }),
|
|
56
|
+
...(skill.cloudId ? { cloud_id: skill.cloudId } : {}),
|
|
57
|
+
...(skill.nativeReference ? { native_reference: skill.nativeReference, display_name: skill.displayName,
|
|
58
|
+
native_scope: skill.nativeScope } : {}),
|
|
59
|
+
})));
|
|
60
|
+
|
|
61
|
+
return requestJson<SyncPushResponse>(`${serverUrl}/portal_skills/sync-push`, jwt, {
|
|
62
|
+
body: {
|
|
63
|
+
skill_sync_protocol: 2,
|
|
64
|
+
skills: payloadSkills,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function downloadSkillBundle(bundleUrl: string): Promise<Buffer> {
|
|
70
|
+
const response = await fetch(bundleUrl, { signal: AbortSignal.timeout(90_000) });
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
const text = await response.text();
|
|
73
|
+
throw new Error(`GET ${bundleUrl} → ${response.status}: ${text}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return Buffer.from(await response.arrayBuffer());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function updateAgentTargets(
|
|
80
|
+
serverUrl: string,
|
|
81
|
+
jwt: string,
|
|
82
|
+
skillId: string,
|
|
83
|
+
targets: Partial<AgentTargets>,
|
|
84
|
+
expectedUpdatedAt?: string,
|
|
85
|
+
native?: { reference: NativeSkillReference; settingsRevision: number },
|
|
86
|
+
): Promise<{ success: boolean; agent_targets: AgentTargets; updated_at?: string }> {
|
|
87
|
+
if (native) {
|
|
88
|
+
checkedNativeReference(native.reference, skillId);
|
|
89
|
+
if (!Number.isSafeInteger(native.settingsRevision) || native.settingsRevision < 0) throw new Error('Refresh native Skill settings before changing assignments.');
|
|
90
|
+
const payload = { operation: 'update', target: { skill_id: skillId, access_revision: native.reference.access_revision },
|
|
91
|
+
revision: native.settingsRevision, patch: { agent_targets: Object.fromEntries(Object.entries(targets).sort(([a], [b]) => a.localeCompare(b))) } };
|
|
92
|
+
const requestId = 'sync-settings-' + createHash('sha256').update(JSON.stringify(payload)).digest('hex');
|
|
93
|
+
const saved = await requestJson<{ receipt_id: string; skill_id: string; target: { skill_id: string }; settings: { agent_targets: AgentTargets; updated_at: string };
|
|
94
|
+
current?: { target: { skill_id: string }; settings: { agent_targets: AgentTargets; updated_at: string } } }>(`${serverUrl}/portal_skills/native-settings`, jwt,
|
|
95
|
+
{ body: { ...payload, request_id: requestId } });
|
|
96
|
+
const current = saved.current || saved;
|
|
97
|
+
if (saved.skill_id !== skillId || typeof saved.receipt_id !== 'string' || !saved.receipt_id
|
|
98
|
+
|| current.target?.skill_id !== skillId || !current.settings) throw new Error('Native assignment update was not confirmed.');
|
|
99
|
+
return { success: true, agent_targets: current.settings.agent_targets, updated_at: current.settings.updated_at };
|
|
100
|
+
}
|
|
101
|
+
return requestJson<{ success: boolean; agent_targets: AgentTargets; updated_at?: string }>(`${serverUrl}/portal_skills/agent-targets`, jwt, {
|
|
102
|
+
method: 'PATCH',
|
|
103
|
+
body: {
|
|
104
|
+
skill_id: skillId,
|
|
105
|
+
agent_targets: targets,
|
|
106
|
+
...(expectedUpdatedAt ? { expected_updated_at: expectedUpdatedAt } : {}),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Install (enabled=true) or uninstall (enabled=false) the curated computer-use
|
|
112
|
+
// skill for the user, matching the desktop app's "Desktop Use" toggle.
|
|
113
|
+
export async function setComputerUseSkill(
|
|
114
|
+
serverUrl: string,
|
|
115
|
+
jwt: string,
|
|
116
|
+
enabled: boolean,
|
|
117
|
+
): Promise<{ installed: boolean }> {
|
|
118
|
+
return requestJson<{ installed: boolean }>(`${serverUrl}/portal_skills/desktop-use`, jwt, {
|
|
119
|
+
body: { enabled, name: 'notis-desktop-use' },
|
|
120
|
+
});
|
|
121
|
+
}
|