broapp 0.2.0 → 0.4.0
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/package.json +1 -1
- package/src/ai/host/adapter.ts +5 -2
- package/src/ai/host/create-ai.ts +235 -7
- package/src/ai/host/fake.ts +11 -4
- package/src/ai/host/from-contract.ts +35 -15
- package/src/ai/host/index.ts +17 -2
- package/src/ai/host/registry.ts +19 -8
- package/src/ai/host/run.ts +326 -37
- package/src/ai/host/threads.ts +366 -0
- package/src/ai/host/tool.ts +67 -55
- package/src/ai/react/AiChat.tsx +49 -1
- package/src/ai/react/AiSettings.tsx +8 -2
- package/src/ai/react/ai.css +14 -0
- package/src/ai/react/index.tsx +3 -0
- package/src/ai/react/use-ai-chat.ts +9 -1
- package/src/ai/shared/contract.ts +110 -1
- package/src/ai/shared/index.ts +3 -0
- package/src/ai/shared/types.check.ts +30 -2
- package/src/ai/shared/types.ts +62 -2
- package/src/cli/main.ts +7 -1
- package/src/host/app.ts +99 -16
- package/src/host/approvals.ts +115 -0
- package/src/host/gate.ts +380 -0
- package/src/host/index.ts +22 -2
- package/src/host/paths.ts +6 -2
- package/src/host/runtime.ts +23 -2
- package/src/shared/contract.ts +49 -6
- package/src/shared/countdown.ts +36 -0
- package/src/shared/errors.ts +56 -2
- package/src/shared/index.ts +6 -1
- package/src/shared/schema.ts +16 -0
package/src/shared/errors.ts
CHANGED
|
@@ -80,6 +80,60 @@ export class PublicError extends Error {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* True when `error` is a {@link PublicError}, including one from another copy
|
|
85
|
+
* of this module.
|
|
86
|
+
*
|
|
87
|
+
* `instanceof` is not enough, and the reason is architectural rather than
|
|
88
|
+
* pedantic. An Autoapp release bundles its own copy of `broapp`, while the
|
|
89
|
+
* child runtime that supervises it has the copy compiled into the launcher —
|
|
90
|
+
* so a `PublicError` thrown by the gate in one and caught by `runOperation` in
|
|
91
|
+
* the other is a different class object with the same shape. Reducing it to
|
|
92
|
+
* "internal error" would silently turn every deliberate refusal, the preview
|
|
93
|
+
* policy's included, into a mystery.
|
|
94
|
+
*
|
|
95
|
+
* The check is deliberately narrow: the name, and a `code` from the known set.
|
|
96
|
+
* Nothing an untrusted value could set by accident.
|
|
97
|
+
*/
|
|
98
|
+
export function isPublicError(error: unknown): error is PublicError {
|
|
99
|
+
// No `instanceof PublicError` fast path. It would be true for one of the two
|
|
100
|
+
// copies and false for the other, and a check whose answer depends on which
|
|
101
|
+
// bundle asked is the bug this function exists to fix — including in the
|
|
102
|
+
// reader's mind, the next time somebody copies this shape.
|
|
103
|
+
if (!(error instanceof Error) || error.name !== 'PublicError') return false;
|
|
104
|
+
const code: unknown = (error as { code?: unknown }).code;
|
|
105
|
+
return typeof code === 'string' && (PUBLIC_CODES as readonly string[]).includes(code);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* True when `error` is a {@link BroappError}, including one from another copy
|
|
110
|
+
* of this module.
|
|
111
|
+
*
|
|
112
|
+
* Same reason as {@link isPublicError}. `fromTransportError` is shared code:
|
|
113
|
+
* the browser calls it inside one bundle, and the Autoapp child runtime calls
|
|
114
|
+
* it on an error that came out of a release's own bundle.
|
|
115
|
+
*/
|
|
116
|
+
function isBroappError(error: unknown): error is BroappError {
|
|
117
|
+
if (!(error instanceof Error) || error.name !== 'BroappError') return false;
|
|
118
|
+
const code: unknown = (error as { code?: unknown }).code;
|
|
119
|
+
return typeof code === 'string' && (PUBLIC_CODES as readonly string[]).includes(code);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* True when `error` is Brobridge's cancellation, from any copy of Brobridge.
|
|
124
|
+
*
|
|
125
|
+
* A release bundles its own, so the class identity is not shared. `ErrorCode`
|
|
126
|
+
* is a set of string constants rather than a symbol, which is what makes the
|
|
127
|
+
* value comparison meaningful across copies.
|
|
128
|
+
*/
|
|
129
|
+
function isCancelled(error: unknown): boolean {
|
|
130
|
+
return (
|
|
131
|
+
error instanceof Error &&
|
|
132
|
+
error.name === 'BridgeError' &&
|
|
133
|
+
(error as { code?: unknown }).code === ErrorCode.CANCELLED
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
83
137
|
/** The message every unhandled host failure becomes, on both sides. */
|
|
84
138
|
export const INTERNAL_ERROR_MESSAGE = 'The application could not complete that operation.';
|
|
85
139
|
|
|
@@ -105,7 +159,7 @@ export class BroappError extends Error {
|
|
|
105
159
|
* for a user to read.
|
|
106
160
|
*/
|
|
107
161
|
export function fromTransportError(error: unknown): BroappError {
|
|
108
|
-
if (error
|
|
162
|
+
if (isBroappError(error)) return error;
|
|
109
163
|
const message = error instanceof Error ? error.message : '';
|
|
110
164
|
if (message.startsWith(MARKER)) {
|
|
111
165
|
const space = message.indexOf(' ');
|
|
@@ -118,7 +172,7 @@ export function fromTransportError(error: unknown): BroappError {
|
|
|
118
172
|
);
|
|
119
173
|
}
|
|
120
174
|
}
|
|
121
|
-
if (error
|
|
175
|
+
if (isCancelled(error)) {
|
|
122
176
|
return new BroappError('rejected', 'The operation was cancelled.', error);
|
|
123
177
|
}
|
|
124
178
|
return new BroappError('internal', INTERNAL_ERROR_MESSAGE, error);
|
package/src/shared/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
export {
|
|
9
9
|
assertNoReservedRoutes,
|
|
10
10
|
defineContract,
|
|
11
|
+
effectOf,
|
|
11
12
|
mergeContracts,
|
|
12
13
|
RESERVED_GROUPS,
|
|
13
14
|
splitRoute,
|
|
@@ -16,6 +17,7 @@ export type {
|
|
|
16
17
|
AnyContract,
|
|
17
18
|
Contract,
|
|
18
19
|
ContractShape,
|
|
20
|
+
Effect,
|
|
19
21
|
ShapeOf,
|
|
20
22
|
OperationInput,
|
|
21
23
|
OperationName,
|
|
@@ -27,7 +29,7 @@ export type {
|
|
|
27
29
|
StreamSpec,
|
|
28
30
|
} from './contract.ts';
|
|
29
31
|
|
|
30
|
-
export { s, ValidationError } from './schema.ts';
|
|
32
|
+
export { isValidationError, s, ValidationError } from './schema.ts';
|
|
31
33
|
export type { Infer, InferObject, Issue, JsonSchema, Result, Schema } from './schema.ts';
|
|
32
34
|
|
|
33
35
|
export {
|
|
@@ -35,8 +37,11 @@ export {
|
|
|
35
37
|
INTERNAL_ERROR_MESSAGE,
|
|
36
38
|
PublicError,
|
|
37
39
|
fromTransportError,
|
|
40
|
+
isPublicError,
|
|
38
41
|
publicError,
|
|
39
42
|
} from './errors.ts';
|
|
40
43
|
export type { PublicErrorCode } from './errors.ts';
|
|
41
44
|
|
|
42
45
|
export { encodeEvent, MAX_EVENT_BYTES, NdjsonDecoder } from './ndjson.ts';
|
|
46
|
+
|
|
47
|
+
export { countdown, isUrgent, remainingMs, URGENT_MS } from './countdown.ts';
|
package/src/shared/schema.ts
CHANGED
|
@@ -35,6 +35,22 @@ export class ValidationError extends Error {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* True when `error` is a {@link ValidationError}, including one from another
|
|
40
|
+
* copy of this module.
|
|
41
|
+
*
|
|
42
|
+
* `instanceof` is not enough for the same reason it is not enough for
|
|
43
|
+
* `PublicError`: an Autoapp release bundles its own copy of `broapp`, so a
|
|
44
|
+
* schema built in one bundle and parsed by code in another throws a different
|
|
45
|
+
* class object with the same shape. Reducing that to "invalid input" with no
|
|
46
|
+
* message would tell a caller nothing about what was actually wrong.
|
|
47
|
+
*/
|
|
48
|
+
export function isValidationError(error: unknown): error is ValidationError {
|
|
49
|
+
return (
|
|
50
|
+
error instanceof Error && error.name === 'ValidationError' && Array.isArray((error as { issues?: unknown }).issues)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
38
54
|
function formatPath(path: IssuePath): string {
|
|
39
55
|
let out = '';
|
|
40
56
|
for (const segment of path) {
|