orizu 0.5.33 → 0.5.35
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/app-commands.d.ts.map +1 -1
- package/dist/app-commands.js +14 -5
- package/dist/app-page-url.d.ts +9 -0
- package/dist/app-page-url.d.ts.map +1 -0
- package/dist/app-page-url.js +12 -0
- package/dist/archive-artifacts-cli.js +2 -2
- package/dist/hosted-agent-prompt.d.ts +1 -12
- package/dist/hosted-agent-prompt.d.ts.map +1 -1
- package/dist/hosted-agent-prompt.js +3 -1
- package/dist/preview-runtime.d.ts +6 -1
- package/dist/preview-runtime.d.ts.map +1 -1
- package/dist/preview-runtime.js +13 -5
- package/package.json +1 -1
- package/src/app-commands.ts +14 -5
- package/src/app-page-url.ts +13 -0
- package/src/archive-artifacts-cli.ts +2 -2
- package/src/hosted-agent-prompt.ts +4 -1
- package/src/preview-runtime.ts +15 -5
- package/vendor/skills/orizu/references/building-apps.md +10 -1
- package/vendor/skills/orizu/references/cli-reference.md +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"AAkCA,iBAAe,QAAQ,kBActB;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY9D;AAED,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1F;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEjD;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb,CAeA;AAED,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM;;;;;IAoB/E;AAED,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAGjE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjE;AAED,iBAAe,iBAAiB,kBAiD/B;AAED,iBAAe,kBAAkB,kBAiDhC;AAED,iBAAe,iBAAiB,kBAiD/B;AAED,iBAAe,cAAc,kBAgD5B;AA+CD,iBAAe,SAAS,kBA2CvB;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAK3G;AAED,iBAAe,eAAe,kBAmD7B;AAED,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,GAChB,CAAA"}
|
package/dist/app-commands.js
CHANGED
|
@@ -7,17 +7,24 @@ import { resolveProjectSlug, fetchApps, selectAppIdInteractively } from './accou
|
|
|
7
7
|
import { printJson, printLine, getErrorMessage } from './cli-console-output.js';
|
|
8
8
|
import { printAppSummaries } from './archive-artifacts-cli.js';
|
|
9
9
|
import { isNodeError, formatTerminalLink } from './auth-commands.js';
|
|
10
|
-
import { authedFetch } from './http.js';
|
|
11
|
-
import {
|
|
10
|
+
import { authedFetch, getBaseUrl } from './http.js';
|
|
11
|
+
import { appPageUrl } from './app-page-url.js';
|
|
12
|
+
import { parseJsonResponse, sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js';
|
|
12
13
|
import { runLocalAppPreview } from './preview-runtime.js';
|
|
13
14
|
async function listApps() {
|
|
14
15
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
15
|
-
const
|
|
16
|
+
const baseUrl = getBaseUrl();
|
|
17
|
+
const apps = (await fetchApps(project, getArchiveListStatus('apps')))
|
|
18
|
+
.map(app => ({ ...app, pageUrl: appPageUrl(baseUrl, app.id) }));
|
|
16
19
|
if (hasJsonFlag()) {
|
|
17
20
|
printJson({ apps });
|
|
18
21
|
return;
|
|
19
22
|
}
|
|
20
23
|
printAppSummaries(apps, printLine);
|
|
24
|
+
// An archived app's page still renders as if live, so it gets no link line.
|
|
25
|
+
apps
|
|
26
|
+
.filter(app => app.status !== 'archived')
|
|
27
|
+
.forEach(app => printLine(`Link: ${sanitizeHumanInlineText(sanitizeTerminalText, app.name || app.id)} ${formatTerminalLink(app.pageUrl)}`));
|
|
21
28
|
}
|
|
22
29
|
function readSourceFile(pathArg) {
|
|
23
30
|
const expandedPath = expandHomePath(pathArg);
|
|
@@ -152,7 +159,7 @@ async function createAppFromFile() {
|
|
|
152
159
|
}
|
|
153
160
|
const data = await parseJsonResponse(response, 'App create');
|
|
154
161
|
if (hasJsonFlag()) {
|
|
155
|
-
printJson({ app: data.app, warnings: data.warnings || [] });
|
|
162
|
+
printJson({ app: { ...data.app, pageUrl: data.app.url || appPageUrl(getBaseUrl(), data.app.id) }, warnings: data.warnings || [] });
|
|
156
163
|
return;
|
|
157
164
|
}
|
|
158
165
|
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`);
|
|
@@ -240,11 +247,13 @@ async function updateAppFromFile() {
|
|
|
240
247
|
throw new Error(`Failed to update app: ${await response.text()}`);
|
|
241
248
|
}
|
|
242
249
|
const data = await parseJsonResponse(response, 'App update');
|
|
250
|
+
const pageUrl = appPageUrl(getBaseUrl(), data.app.id);
|
|
243
251
|
if (hasJsonFlag()) {
|
|
244
|
-
printJson({ app: data.app, warnings: data.warnings || [] });
|
|
252
|
+
printJson({ app: { ...data.app, pageUrl }, warnings: data.warnings || [] });
|
|
245
253
|
return;
|
|
246
254
|
}
|
|
247
255
|
printLine(`Updated app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) to v${data.app.versionNum}`);
|
|
256
|
+
printLine(`View app: ${formatTerminalLink(pageUrl)}`);
|
|
248
257
|
if (data.warnings?.length) {
|
|
249
258
|
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`);
|
|
250
259
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app's page lives in the web app (ORI-2342): `/preview/<app id>`,
|
|
3
|
+
* the route in apps/web/app/preview/[id]/page.tsx. `orizu apps list`,
|
|
4
|
+
* `orizu apps update` and the hosted agent's prompt build their links from
|
|
5
|
+
* here. `orizu apps create` prints the link the server returns instead.
|
|
6
|
+
*/
|
|
7
|
+
export declare function appPagePath(appId: string): string;
|
|
8
|
+
export declare function appPageUrl(baseUrl: string, appId: string): string;
|
|
9
|
+
//# sourceMappingURL=app-page-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-page-url.d.ts","sourceRoot":"","sources":["../src/app-page-url.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app's page lives in the web app (ORI-2342): `/preview/<app id>`,
|
|
3
|
+
* the route in apps/web/app/preview/[id]/page.tsx. `orizu apps list`,
|
|
4
|
+
* `orizu apps update` and the hosted agent's prompt build their links from
|
|
5
|
+
* here. `orizu apps create` prints the link the server returns instead.
|
|
6
|
+
*/
|
|
7
|
+
export function appPagePath(appId) {
|
|
8
|
+
return `/preview/${appId}`;
|
|
9
|
+
}
|
|
10
|
+
export function appPageUrl(baseUrl, appId) {
|
|
11
|
+
return `${baseUrl.replace(/\/+$/, '')}${appPagePath(encodeURIComponent(appId))}`;
|
|
12
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { authedFetch } from './http.js';
|
|
9
9
|
import { extractErrorMessage } from './error-response.js';
|
|
10
|
-
import { sanitizeTerminalText } from './json-response.js';
|
|
10
|
+
import { sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js';
|
|
11
11
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
12
12
|
const ARTIFACT_TYPES = {
|
|
13
13
|
app: 'app',
|
|
@@ -61,7 +61,7 @@ export function printAppSummaries(items, print) {
|
|
|
61
61
|
return print('No apps found.');
|
|
62
62
|
printTable(['APP ID', 'APP NAME', 'VERSION', 'ARCHIVE'], items.map(item => [
|
|
63
63
|
sanitizeTerminalText(item.id),
|
|
64
|
-
sanitizeTerminalText
|
|
64
|
+
sanitizeHumanInlineText(sanitizeTerminalText, item.name || '-'),
|
|
65
65
|
`v${item.currentVersionNum || 1}`,
|
|
66
66
|
sanitizeTerminalText(item.status || 'active'),
|
|
67
67
|
]), print);
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The system prompt for the hosted agent (ORI-2207).
|
|
3
|
-
*
|
|
4
|
-
* OpenCode (the program that runs the agent in a hosted session) ships its own
|
|
5
|
-
* built-in prompt that starts "You are opencode, an interactive CLI tool…", so
|
|
6
|
-
* the agent used to introduce itself as OpenCode. We register our own "primary
|
|
7
|
-
* agent" in the OpenCode config with this text, and every prompt request picks
|
|
8
|
-
* it by name. That replaces OpenCode's built-in prompt entirely, so this text
|
|
9
|
-
* carries the working rules we still want: use the tools, keep answers short.
|
|
10
|
-
* AGENTS.md is still added after it, as before.
|
|
11
|
-
*/
|
|
12
1
|
export declare const HOSTED_AGENT_NAME = "orizu";
|
|
13
|
-
export declare const HOSTED_AGENT_PROMPT
|
|
2
|
+
export declare const HOSTED_AGENT_PROMPT: string;
|
|
14
3
|
//# sourceMappingURL=hosted-agent-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-agent-prompt.d.ts","sourceRoot":"","sources":["../src/hosted-agent-prompt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hosted-agent-prompt.d.ts","sourceRoot":"","sources":["../src/hosted-agent-prompt.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,iBAAiB,UAAU,CAAA;AAExC,eAAO,MAAM,mBAAmB,QAK4Z,CAAA"}
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
* carries the working rules we still want: use the tools, keep answers short.
|
|
10
10
|
* AGENTS.md is still added after it, as before.
|
|
11
11
|
*/
|
|
12
|
+
import { appPagePath } from './app-page-url.js';
|
|
12
13
|
export const HOSTED_AGENT_NAME = 'orizu';
|
|
13
14
|
export const HOSTED_AGENT_PROMPT = `You are the Orizu agent. You work in the person's repository inside an Orizu workbench, helping them with software engineering tasks. If asked who or what you are, say you are the Orizu agent. Never call yourself OpenCode.
|
|
14
15
|
|
|
15
16
|
- Do the work with your tools: read files, search, edit, and run commands. Do not guess at what a file contains when you can look.
|
|
16
17
|
- Keep answers short and plain. Say what you did and what the person needs to know next.
|
|
17
|
-
- Follow the repository's own conventions and any instructions in its AGENTS.md
|
|
18
|
+
- Follow the repository's own conventions and any instructions in its AGENTS.md.
|
|
19
|
+
- An Orizu app's page link is <Orizu server>${appPagePath('<app id>')}, where <Orizu server> is the server the orizu CLI talks to (https://app.orizu.ai by default). To give someone an app's link, run \`orizu projects list\` to get the \`<team>/<project>\` slug, then \`orizu apps list --project <team>/<project>\`: it prints each app's full link. The --project flag is required here: prompts cannot run in this environment. Never guess a link.`;
|
|
@@ -64,7 +64,12 @@ export declare function runLocalAppPreview(options: AppPreviewOptions): Promise<
|
|
|
64
64
|
* an actionable message instead. Exported for tests.
|
|
65
65
|
*/
|
|
66
66
|
export declare function findMissingPreviewRuntimeDeps(nodeModuleDirs: string[]): string[];
|
|
67
|
-
|
|
67
|
+
declare function loadPreviewCssModules(): Promise<{
|
|
68
|
+
postcss: typeof import("postcss").default;
|
|
69
|
+
tailwind: import("postcss/lib/postcss").PluginCreator<import("@tailwindcss/postcss").PluginOptions>;
|
|
70
|
+
}>;
|
|
71
|
+
/** `loadModules` is for tests: one that fails stands in for a broken install. */
|
|
72
|
+
export declare function buildPreviewCss(repoRoot: string | null, appPath: string, loadModules?: typeof loadPreviewCssModules): Promise<string>;
|
|
68
73
|
export declare function getPreviewSnapshotModulePaths(): string[];
|
|
69
74
|
export {};
|
|
70
75
|
//# sourceMappingURL=preview-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-runtime.d.ts","sourceRoot":"","sources":["../src/preview-runtime.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,gCAAgC,IAAI,CAAA;AAGjD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA+C5D,CAAA;AAGD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,UAAU,KAAK;IACb,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE;QACR,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;KACtE,CAAA;CACF;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;IACnE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;IACvD,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;IACrD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;CACvD;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACzE,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACzF,UAAU,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC9E,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACrD,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;IACvD,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;IACrD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAA;CACvD;AAQD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkClD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,GAAG,KAAK,EAAE,CASzE;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"preview-runtime.d.ts","sourceRoot":"","sources":["../src/preview-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/preview-runtime.js
CHANGED
|
@@ -130,7 +130,6 @@ export async function runLocalAppPreview(options) {
|
|
|
130
130
|
const cssPath = join(tempDir, 'preview.css');
|
|
131
131
|
const htmlPath = join(tempDir, 'index.html');
|
|
132
132
|
const outDir = join(tempDir, 'dist');
|
|
133
|
-
writeFileSync(cssPath, await buildPreviewCss(repoRoot, appPath), 'utf8');
|
|
134
133
|
writeFileSync(entryPath, buildEntrySource(appPath, options.sampleRow), 'utf8');
|
|
135
134
|
writeFileSync(htmlPath, buildPreviewHtml(), 'utf8');
|
|
136
135
|
let server = null;
|
|
@@ -149,6 +148,8 @@ export async function runLocalAppPreview(options) {
|
|
|
149
148
|
'(run inside a project that has them, `npm install react react-dom` next to your app, ' +
|
|
150
149
|
'or run from an Orizu checkout after `bun install`).');
|
|
151
150
|
}
|
|
151
|
+
// After the dependency checks, so their actionable errors come before a Tailwind warning.
|
|
152
|
+
writeFileSync(cssPath, await buildPreviewCss(repoRoot, appPath), 'utf8');
|
|
152
153
|
await esbuild.build({
|
|
153
154
|
entryPoints: [entryPath],
|
|
154
155
|
bundle: true,
|
|
@@ -550,11 +551,15 @@ function buildPreviewHtml() {
|
|
|
550
551
|
</html>
|
|
551
552
|
`;
|
|
552
553
|
}
|
|
553
|
-
|
|
554
|
+
const PREVIEW_TAILWIND_FALLBACK_WARNING = 'Tailwind CSS could not be built; the preview uses fallback styles';
|
|
555
|
+
async function loadPreviewCssModules() {
|
|
556
|
+
return { postcss: (await import('postcss')).default, tailwind: (await import('@tailwindcss/postcss')).default };
|
|
557
|
+
}
|
|
558
|
+
/** `loadModules` is for tests: one that fails stands in for a broken install. */
|
|
559
|
+
export async function buildPreviewCss(repoRoot, appPath, loadModules = loadPreviewCssModules) {
|
|
554
560
|
const fallbackCss = buildPreviewChromeCss();
|
|
555
561
|
try {
|
|
556
|
-
const postcss =
|
|
557
|
-
const tailwind = (await import('@tailwindcss/postcss')).default;
|
|
562
|
+
const { postcss, tailwind } = await loadModules();
|
|
558
563
|
const cliPackageRoot = findCliPackageRoot();
|
|
559
564
|
const globalsPath = repoRoot
|
|
560
565
|
? join(repoRoot, 'app', 'globals.css')
|
|
@@ -576,7 +581,10 @@ export async function buildPreviewCss(repoRoot, appPath) {
|
|
|
576
581
|
const result = await postcss([tailwind()]).process(sourceCss, { from: globalsPath });
|
|
577
582
|
return result.css;
|
|
578
583
|
}
|
|
579
|
-
catch {
|
|
584
|
+
catch (error) {
|
|
585
|
+
// Without Tailwind the screenshot loses the app's utility styling, so say so
|
|
586
|
+
// instead of looking right (ORI-2261: the sandbox tools check fails on it).
|
|
587
|
+
process.stderr.write(`warning: ${PREVIEW_TAILWIND_FALLBACK_WARNING} (${error instanceof Error ? error.message : String(error)})\n`);
|
|
580
588
|
return fallbackCss;
|
|
581
589
|
}
|
|
582
590
|
}
|
package/package.json
CHANGED
package/src/app-commands.ts
CHANGED
|
@@ -25,20 +25,27 @@ import { resolveProjectSlug, fetchApps, selectAppIdInteractively } from './accou
|
|
|
25
25
|
import { printJson, printLine, getErrorMessage } from './cli-console-output.js'
|
|
26
26
|
import { printAppSummaries } from './archive-artifacts-cli.js'
|
|
27
27
|
import { isNodeError, formatTerminalLink } from './auth-commands.js'
|
|
28
|
-
import { authedFetch } from './http.js'
|
|
29
|
-
import {
|
|
28
|
+
import { authedFetch, getBaseUrl } from './http.js'
|
|
29
|
+
import { appPageUrl } from './app-page-url.js'
|
|
30
|
+
import { parseJsonResponse, sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js'
|
|
30
31
|
import { runLocalAppPreview } from './preview-runtime.js'
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
async function listApps() {
|
|
35
36
|
const project = getArg('--project') || await resolveProjectSlug(null)
|
|
36
|
-
const
|
|
37
|
+
const baseUrl = getBaseUrl()
|
|
38
|
+
const apps = (await fetchApps(project, getArchiveListStatus('apps')))
|
|
39
|
+
.map(app => ({ ...app, pageUrl: appPageUrl(baseUrl, app.id) }))
|
|
37
40
|
if (hasJsonFlag()) {
|
|
38
41
|
printJson({ apps })
|
|
39
42
|
return
|
|
40
43
|
}
|
|
41
44
|
printAppSummaries(apps, printLine)
|
|
45
|
+
// An archived app's page still renders as if live, so it gets no link line.
|
|
46
|
+
apps
|
|
47
|
+
.filter(app => app.status !== 'archived')
|
|
48
|
+
.forEach(app => printLine(`Link: ${sanitizeHumanInlineText(sanitizeTerminalText, app.name || app.id)} ${formatTerminalLink(app.pageUrl)}`))
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
function readSourceFile(pathArg: string): string {
|
|
@@ -195,7 +202,7 @@ async function createAppFromFile() {
|
|
|
195
202
|
warnings?: string[]
|
|
196
203
|
}>(response, 'App create')
|
|
197
204
|
if (hasJsonFlag()) {
|
|
198
|
-
printJson({ app: data.app, warnings: data.warnings || [] })
|
|
205
|
+
printJson({ app: { ...data.app, pageUrl: data.app.url || appPageUrl(getBaseUrl(), data.app.id) }, warnings: data.warnings || [] })
|
|
199
206
|
return
|
|
200
207
|
}
|
|
201
208
|
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`)
|
|
@@ -297,11 +304,13 @@ async function updateAppFromFile() {
|
|
|
297
304
|
app: { id: string; name: string; versionNum: number; componentName?: string }
|
|
298
305
|
warnings?: string[]
|
|
299
306
|
}>(response, 'App update')
|
|
307
|
+
const pageUrl = appPageUrl(getBaseUrl(), data.app.id)
|
|
300
308
|
if (hasJsonFlag()) {
|
|
301
|
-
printJson({ app: data.app, warnings: data.warnings || [] })
|
|
309
|
+
printJson({ app: { ...data.app, pageUrl }, warnings: data.warnings || [] })
|
|
302
310
|
return
|
|
303
311
|
}
|
|
304
312
|
printLine(`Updated app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) to v${data.app.versionNum}`)
|
|
313
|
+
printLine(`View app: ${formatTerminalLink(pageUrl)}`)
|
|
305
314
|
if (data.warnings?.length) {
|
|
306
315
|
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`)
|
|
307
316
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app's page lives in the web app (ORI-2342): `/preview/<app id>`,
|
|
3
|
+
* the route in apps/web/app/preview/[id]/page.tsx. `orizu apps list`,
|
|
4
|
+
* `orizu apps update` and the hosted agent's prompt build their links from
|
|
5
|
+
* here. `orizu apps create` prints the link the server returns instead.
|
|
6
|
+
*/
|
|
7
|
+
export function appPagePath(appId: string): string {
|
|
8
|
+
return `/preview/${appId}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function appPageUrl(baseUrl: string, appId: string): string {
|
|
12
|
+
return `${baseUrl.replace(/\/+$/, '')}${appPagePath(encodeURIComponent(appId))}`
|
|
13
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { authedFetch } from './http.js'
|
|
10
10
|
import { extractErrorMessage } from './error-response.js'
|
|
11
|
-
import { sanitizeTerminalText } from './json-response.js'
|
|
11
|
+
import { sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js'
|
|
12
12
|
|
|
13
13
|
type ArchiveStatus = 'active' | 'archived' | 'all'
|
|
14
14
|
type ArchiveAction = 'archive' | 'restore'
|
|
@@ -148,7 +148,7 @@ export function printAppSummaries(items: AppSummary[], print: PrintLine) {
|
|
|
148
148
|
['APP ID', 'APP NAME', 'VERSION', 'ARCHIVE'],
|
|
149
149
|
items.map(item => [
|
|
150
150
|
sanitizeTerminalText(item.id),
|
|
151
|
-
sanitizeTerminalText
|
|
151
|
+
sanitizeHumanInlineText(sanitizeTerminalText, item.name || '-'),
|
|
152
152
|
`v${item.currentVersionNum || 1}`,
|
|
153
153
|
sanitizeTerminalText(item.status || 'active'),
|
|
154
154
|
]),
|
|
@@ -9,10 +9,13 @@
|
|
|
9
9
|
* carries the working rules we still want: use the tools, keep answers short.
|
|
10
10
|
* AGENTS.md is still added after it, as before.
|
|
11
11
|
*/
|
|
12
|
+
import { appPagePath } from './app-page-url.js'
|
|
13
|
+
|
|
12
14
|
export const HOSTED_AGENT_NAME = 'orizu'
|
|
13
15
|
|
|
14
16
|
export const HOSTED_AGENT_PROMPT = `You are the Orizu agent. You work in the person's repository inside an Orizu workbench, helping them with software engineering tasks. If asked who or what you are, say you are the Orizu agent. Never call yourself OpenCode.
|
|
15
17
|
|
|
16
18
|
- Do the work with your tools: read files, search, edit, and run commands. Do not guess at what a file contains when you can look.
|
|
17
19
|
- Keep answers short and plain. Say what you did and what the person needs to know next.
|
|
18
|
-
- Follow the repository's own conventions and any instructions in its AGENTS.md
|
|
20
|
+
- Follow the repository's own conventions and any instructions in its AGENTS.md.
|
|
21
|
+
- An Orizu app's page link is <Orizu server>${appPagePath('<app id>')}, where <Orizu server> is the server the orizu CLI talks to (https://app.orizu.ai by default). To give someone an app's link, run \`orizu projects list\` to get the \`<team>/<project>\` slug, then \`orizu apps list --project <team>/<project>\`: it prints each app's full link. The --project flag is required here: prompts cannot run in this environment. Never guess a link.`
|
package/src/preview-runtime.ts
CHANGED
|
@@ -193,7 +193,6 @@ export async function runLocalAppPreview(options: AppPreviewOptions): Promise<Ap
|
|
|
193
193
|
const htmlPath = join(tempDir, 'index.html')
|
|
194
194
|
const outDir = join(tempDir, 'dist')
|
|
195
195
|
|
|
196
|
-
writeFileSync(cssPath, await buildPreviewCss(repoRoot, appPath), 'utf8')
|
|
197
196
|
writeFileSync(entryPath, buildEntrySource(appPath, options.sampleRow), 'utf8')
|
|
198
197
|
writeFileSync(htmlPath, buildPreviewHtml(), 'utf8')
|
|
199
198
|
|
|
@@ -219,6 +218,8 @@ export async function runLocalAppPreview(options: AppPreviewOptions): Promise<Ap
|
|
|
219
218
|
)
|
|
220
219
|
}
|
|
221
220
|
|
|
221
|
+
// After the dependency checks, so their actionable errors come before a Tailwind warning.
|
|
222
|
+
writeFileSync(cssPath, await buildPreviewCss(repoRoot, appPath), 'utf8')
|
|
222
223
|
await esbuild.build({
|
|
223
224
|
entryPoints: [entryPath],
|
|
224
225
|
bundle: true,
|
|
@@ -656,12 +657,18 @@ function buildPreviewHtml() {
|
|
|
656
657
|
`
|
|
657
658
|
}
|
|
658
659
|
|
|
659
|
-
|
|
660
|
+
const PREVIEW_TAILWIND_FALLBACK_WARNING = 'Tailwind CSS could not be built; the preview uses fallback styles'
|
|
661
|
+
|
|
662
|
+
async function loadPreviewCssModules() {
|
|
663
|
+
return { postcss: (await import('postcss')).default, tailwind: (await import('@tailwindcss/postcss')).default }
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/** `loadModules` is for tests: one that fails stands in for a broken install. */
|
|
667
|
+
export async function buildPreviewCss(repoRoot: string | null, appPath: string, loadModules: typeof loadPreviewCssModules = loadPreviewCssModules) {
|
|
660
668
|
const fallbackCss = buildPreviewChromeCss()
|
|
661
669
|
|
|
662
670
|
try {
|
|
663
|
-
const postcss =
|
|
664
|
-
const tailwind = (await import('@tailwindcss/postcss')).default
|
|
671
|
+
const { postcss, tailwind } = await loadModules()
|
|
665
672
|
const cliPackageRoot = findCliPackageRoot()
|
|
666
673
|
const globalsPath = repoRoot
|
|
667
674
|
? join(repoRoot, 'app', 'globals.css')
|
|
@@ -682,7 +689,10 @@ export async function buildPreviewCss(repoRoot: string | null, appPath: string)
|
|
|
682
689
|
].join('\n')
|
|
683
690
|
const result = await postcss([tailwind()]).process(sourceCss, { from: globalsPath })
|
|
684
691
|
return result.css
|
|
685
|
-
} catch {
|
|
692
|
+
} catch (error) {
|
|
693
|
+
// Without Tailwind the screenshot loses the app's utility styling, so say so
|
|
694
|
+
// instead of looking right (ORI-2261: the sandbox tools check fails on it).
|
|
695
|
+
process.stderr.write(`warning: ${PREVIEW_TAILWIND_FALLBACK_WARNING} (${error instanceof Error ? error.message : String(error)})\n`)
|
|
686
696
|
return fallbackCss
|
|
687
697
|
}
|
|
688
698
|
}
|
|
@@ -1580,7 +1580,16 @@ orizu apps preview \
|
|
|
1580
1580
|
|
|
1581
1581
|
The command validates the same app contract and allowed import registry as upload, validates the sample row against `input.json`, serves a temporary static preview page, passes `inputData`, `initialValues`, and `onComplete`, then uses Playwright to render it. Add `--headed` for visible Chromium review, and `--keep-open` when you want to inspect the local page manually. In the Orizu web checkout, preview uses the live component tree and global Tailwind CSS; in the mirrored/published CLI package, it uses the bundled preview runtime snapshot so the workflow remains available without the site source tree.
|
|
1582
1582
|
|
|
1583
|
-
|
|
1583
|
+
In a hosted session, the sandbox already has the preview tooling and a headless Chromium. Run `orizu apps preview` with `--screenshot` as shown above; `--headed` and `--keep-open` are for local use and do not work in a sandbox. Do not `npm install` anything for it, including `react` or `react-dom`. If preview still fails there, run the plain-`node` smoke test (`scripts/test-app.mjs`) to check the app contract, then file the preview failure:
|
|
1584
|
+
|
|
1585
|
+
```bash
|
|
1586
|
+
orizu feedback --category bug --severity major \
|
|
1587
|
+
--summary "orizu apps preview fails in the hosted sandbox" \
|
|
1588
|
+
--tried "<the orizu apps preview command you ran>" \
|
|
1589
|
+
--actual "<the error it printed, without customer content>"
|
|
1590
|
+
```
|
|
1591
|
+
|
|
1592
|
+
Locally, the published CLI does not install the preview tooling (`esbuild`, `react`, `react-dom`, `@playwright/test`, Tailwind): run preview inside a project that provides them or from an Orizu checkout. When they are missing the command exits with an actionable error; the plain-`node` smoke test (`scripts/test-app.mjs`) still works everywhere in the meantime.
|
|
1584
1593
|
|
|
1585
1594
|
For coding agents: do not treat a passing contract check as enough. After generating or editing an app, run `orizu apps preview` with a representative row, inspect the screenshot, and compare the rendered workflow to the user's likely intent: are the right fields visible, is the primary judgment obvious, do controls fit, and would a human reviewer know what to do? If the screenshot looks wrong, revise the app and preview again before publishing.
|
|
1586
1595
|
|
|
@@ -272,6 +272,8 @@ orizu apps archive <app-id> --project my-team/quality-eval
|
|
|
272
272
|
orizu apps restore <app-id> --project my-team/quality-eval
|
|
273
273
|
```
|
|
274
274
|
|
|
275
|
+
An app's page link is `<server>/preview/<app-id>` (`https://app.orizu.ai` by default). `apps list` prints a `Link: <app> <link>` line under the table for each app that is not archived; `apps list --json` has `pageUrl` for each app. `apps create` and `apps update` print it after `View app:`; `apps create --json` and `apps update --json` both have it as `app.pageUrl`. Get `<team>/<project>` from `orizu projects list`. Give that link; never guess one.
|
|
276
|
+
|
|
275
277
|
Create from file:
|
|
276
278
|
|
|
277
279
|
```bash
|