@wirecat/drive-cli 0.3.0 → 0.5.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/README.md +4 -3
- package/dist/api-contract.d.ts.map +1 -1
- package/dist/api-contract.js +4 -2
- package/dist/api-contract.js.map +1 -1
- package/dist/bin/drive.js +16 -20
- package/dist/bin/drive.js.map +1 -1
- package/dist/catalog-commands.d.ts +13 -0
- package/dist/catalog-commands.d.ts.map +1 -0
- package/dist/catalog-commands.js +111 -0
- package/dist/catalog-commands.js.map +1 -0
- package/dist/catalog.d.ts +43 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +107 -0
- package/dist/catalog.js.map +1 -0
- package/dist/config.d.ts +244 -39
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -12
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +13 -5
- package/dist/errors.js.map +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.d.ts.map +1 -1
- package/dist/extraction.js +9 -5
- package/dist/extraction.js.map +1 -1
- package/dist/failure.d.ts +65 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +87 -0
- package/dist/failure.js.map +1 -0
- package/dist/google-api.d.ts.map +1 -1
- package/dist/google-api.js +3 -1
- package/dist/google-api.js.map +1 -1
- package/dist/google.d.ts +4 -0
- package/dist/google.d.ts.map +1 -1
- package/dist/google.js +23 -9
- package/dist/google.js.map +1 -1
- package/dist/knowledge-commands.d.ts.map +1 -1
- package/dist/knowledge-commands.js +9 -5
- package/dist/knowledge-commands.js.map +1 -1
- package/dist/knowledge.d.ts +1 -1
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +10 -4
- package/dist/knowledge.js.map +1 -1
- package/dist/login.d.ts +1 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +11 -5
- package/dist/login.js.map +1 -1
- package/dist/mcp.d.ts +77 -4
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +101 -27
- package/dist/mcp.js.map +1 -1
- package/dist/model.d.ts +55 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +16 -0
- package/dist/model.js.map +1 -1
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +66 -0
- package/dist/output.js.map +1 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +7 -4
- package/dist/policy.js.map +1 -1
- package/dist/profile-lock.d.ts.map +1 -1
- package/dist/profile-lock.js +4 -2
- package/dist/profile-lock.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +99 -40
- package/dist/program.js.map +1 -1
- package/dist/registry.d.ts +4 -34
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +9 -14
- package/dist/registry.js.map +1 -1
- package/dist/remote-commands.d.ts.map +1 -1
- package/dist/remote-commands.js +9 -5
- package/dist/remote-commands.js.map +1 -1
- package/dist/scope.d.ts +3 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +15 -0
- package/dist/scope.js.map +1 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +17 -4
- package/dist/state.js.map +1 -1
- package/dist/store.d.ts +4 -2
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +92 -12
- package/dist/store.js.map +1 -1
- package/dist/sync.d.ts +6 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +91 -44
- package/dist/sync.js.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +8 -4
- package/dist/tokens.js.map +1 -1
- package/package.json +4 -3
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ItemEnvelope, ListEnvelope } from "@wirecat/cli-base/standards";
|
|
2
|
+
export declare const snakeKeys: (value: unknown, record?: boolean) => unknown;
|
|
3
|
+
/** One invocation's standard envelope, shared by CLI output and the MCP executor. */
|
|
4
|
+
export declare const answerOf: (value: unknown, context: {
|
|
5
|
+
startedAt: number;
|
|
6
|
+
runId?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
}) => ItemEnvelope<unknown> | ListEnvelope<unknown>;
|
|
9
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAQ,MAAM,6BAA6B,CAAA;AAyBnF,eAAO,MAAM,SAAS,UAAW,OAAO,uBAAmB,OAS1D,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,QAAQ,UACZ,OAAO,WACL;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7D,YAAY,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,OAAO,CA8B9C,CAAA"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
// Provider/user dictionaries retain their vocabulary; profile/model names are identifiers.
|
|
3
|
+
const VERBATIM = new Set([
|
|
4
|
+
"frontMatter",
|
|
5
|
+
"front_matter",
|
|
6
|
+
"provider_metadata",
|
|
7
|
+
"metadata",
|
|
8
|
+
"headers",
|
|
9
|
+
"properties",
|
|
10
|
+
"appProperties",
|
|
11
|
+
"app_properties",
|
|
12
|
+
"request_schema",
|
|
13
|
+
"response_schema",
|
|
14
|
+
"body_schema",
|
|
15
|
+
"schema",
|
|
16
|
+
"inputSchema",
|
|
17
|
+
"input_schema",
|
|
18
|
+
"outputSchema",
|
|
19
|
+
"output_schema",
|
|
20
|
+
]);
|
|
21
|
+
const RECORDS = new Set(["profiles", "permissions", "models"]);
|
|
22
|
+
const keyOf = (key) => /^[a-z][a-zA-Z0-9]*$/.test(key) ? key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase() : key;
|
|
23
|
+
export const snakeKeys = (value, record = false) => {
|
|
24
|
+
if (Array.isArray(value))
|
|
25
|
+
return value.map((item) => snakeKeys(item));
|
|
26
|
+
if (!value || typeof value !== "object" || value instanceof Date)
|
|
27
|
+
return value;
|
|
28
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
29
|
+
record ? key : keyOf(key),
|
|
30
|
+
VERBATIM.has(key) ? item : snakeKeys(item, RECORDS.has(key)),
|
|
31
|
+
]));
|
|
32
|
+
};
|
|
33
|
+
/** One invocation's standard envelope, shared by CLI output and the MCP executor. */
|
|
34
|
+
export const answerOf = (value, context) => {
|
|
35
|
+
const data = snakeKeys(value);
|
|
36
|
+
const meta = {
|
|
37
|
+
run_id: context.runId ?? randomUUID(),
|
|
38
|
+
duration_ms: Math.max(0, Math.round(Date.now() - context.startedAt)),
|
|
39
|
+
};
|
|
40
|
+
// Rich results (search/context/config) stay together in an item, rather than losing their metadata.
|
|
41
|
+
const list = Array.isArray(data)
|
|
42
|
+
? { items: data, has_more: false }
|
|
43
|
+
: data &&
|
|
44
|
+
typeof data === "object" &&
|
|
45
|
+
"items" in data &&
|
|
46
|
+
Array.isArray(data.items) &&
|
|
47
|
+
Object.keys(data).every((key) => ["items", "has_more", "next_offset"].includes(key))
|
|
48
|
+
? data
|
|
49
|
+
: undefined;
|
|
50
|
+
if (!list)
|
|
51
|
+
return { item: data, meta };
|
|
52
|
+
const items = list.items;
|
|
53
|
+
const hasMore = "has_more" in list && list.has_more === true;
|
|
54
|
+
return {
|
|
55
|
+
items,
|
|
56
|
+
page: {
|
|
57
|
+
limit: context.limit ?? Math.max(1, items.length),
|
|
58
|
+
has_more: hasMore,
|
|
59
|
+
...("next_offset" in list && list.next_offset !== null && list.next_offset !== undefined
|
|
60
|
+
? { cursor: String(list.next_offset) }
|
|
61
|
+
: {}),
|
|
62
|
+
},
|
|
63
|
+
meta,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
package/dist/policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AACD,eAAO,MAAM,cAAc,QAAS,MAAM,CAAC,UAAU,WAAW,MAAM,UAAS,WAAW;;;CASzF,CAAA;AAID,eAAO,MAAM,gBAAgB,WAAY,MAAM,aAa9C,CAAA;AACD,eAAO,MAAM,WAAW,QACjB,MAAM,CAAC,UAAU,WACb,MAAM,OACV,MAAM,WACF,OAAO,UACT,WAAW,QACZ,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AACD,eAAO,MAAM,cAAc,QAAS,MAAM,CAAC,UAAU,WAAW,MAAM,UAAS,WAAW;;;CASzF,CAAA;AAID,eAAO,MAAM,gBAAgB,WAAY,MAAM,aAa9C,CAAA;AACD,eAAO,MAAM,WAAW,QACjB,MAAM,CAAC,UAAU,WACb,MAAM,OACV,MAAM,WACF,OAAO,UACT,WAAW,QACZ,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,kBAqBxC,CAAA;AACD,eAAO,MAAM,kBAAkB,GAAU,CAAC,OACnC,MAAM,CAAC,UAAU,WACb,MAAM,OACV,MAAM,OACN,MAAM,OAAO,CAAC,CAAC,CAAC,UACd,WAAW,QACZ,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KACtC,OAAO,CAAC,CAAC,CAoBX,CAAA"}
|
package/dist/policy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { CliError } from "@wirecat/cli-base";
|
|
3
|
-
import { guardedWrite, layerPermissions, levelFor, newOperationId, permissionOverrides, RecipientList, SendJournal, sendGuard, } from "@wirecat/cli-
|
|
3
|
+
import { guardedWrite, layerPermissions, levelFor, newOperationId, permissionOverrides, RecipientList, SendJournal, sendGuard, } from "@wirecat/cli-core/sends";
|
|
4
4
|
import { operations } from "./api-contract.js";
|
|
5
5
|
import { paths, readConfig } from "./config.js";
|
|
6
6
|
import { VERSION } from "./version.js";
|
|
@@ -12,7 +12,7 @@ export const policySettings = (env, profile, flags = {}) => {
|
|
|
12
12
|
["profile", own?.permissions],
|
|
13
13
|
["defaults", config.defaults?.permissions],
|
|
14
14
|
]);
|
|
15
|
-
return { levels, readOnly: flags.readOnly === true || (own?.
|
|
15
|
+
return { levels, readOnly: flags.readOnly === true || (own?.read_only ?? config.defaults?.read_only ?? false) };
|
|
16
16
|
};
|
|
17
17
|
const defaults = Object.fromEntries(operations.filter((op) => op.effect === "destructive").map((op) => [`api.${op.id}`, "ask"]));
|
|
18
18
|
export const methodPolicyKeys = (method) => {
|
|
@@ -33,7 +33,10 @@ export const checkPolicy = async (env, profile, key, mutates, flags = {}, ask) =
|
|
|
33
33
|
const { levels, readOnly } = policySettings(env, profile, flags);
|
|
34
34
|
const { level } = levelFor(levels, key, defaults);
|
|
35
35
|
if (level === "deny" || (mutates && (readOnly || level === "readonly")))
|
|
36
|
-
throw new CliError("permission_error", "profile policy refuses this operation", {
|
|
36
|
+
throw new CliError("permission_error", "profile policy refuses this operation", {
|
|
37
|
+
reason: "policy.denied",
|
|
38
|
+
permission: key,
|
|
39
|
+
});
|
|
37
40
|
if (mutates && level === "ask" && !flags.dryRun) {
|
|
38
41
|
const destructive = defaults[key] === "ask";
|
|
39
42
|
if (destructive ? flags.allowDangerous : flags.yes)
|
|
@@ -42,7 +45,7 @@ export const checkPolicy = async (env, profile, key, mutates, flags = {}, ask) =
|
|
|
42
45
|
return;
|
|
43
46
|
throw new CliError("confirmation_required", destructive
|
|
44
47
|
? "this deletion requires --allow-dangerous or an explicit permission"
|
|
45
|
-
: "profile policy requires --yes or confirmation", { permission: key });
|
|
48
|
+
: "profile policy requires --yes or confirmation", { reason: "policy.confirm", permission: key });
|
|
46
49
|
}
|
|
47
50
|
};
|
|
48
51
|
export const guardedGoogleWrite = async (env, profile, key, act, flags = {}, ask) => {
|
package/dist/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EACL,YAAY,EAEZ,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,SAAS,GACV,MAAM,
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-lock.d.ts","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,QAAe,MAAM,CAAC,UAAU,QAAQ,MAAM;;;
|
|
1
|
+
{"version":3,"file":"profile-lock.d.ts","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,QAAe,MAAM,CAAC,UAAU,QAAQ,MAAM;;;EA2BrE,CAAA"}
|
package/dist/profile-lock.js
CHANGED
|
@@ -16,12 +16,14 @@ export const lockProfile = async (env, name) => {
|
|
|
16
16
|
release,
|
|
17
17
|
assertHeld: () => {
|
|
18
18
|
if (compromised)
|
|
19
|
-
throw new CliError("provider_unavailable", "profile lock was lost; retry the operation"
|
|
19
|
+
throw new CliError("provider_unavailable", "profile lock was lost; retry the operation", {
|
|
20
|
+
reason: "profile.locked",
|
|
21
|
+
});
|
|
20
22
|
},
|
|
21
23
|
};
|
|
22
24
|
}
|
|
23
25
|
catch {
|
|
24
|
-
throw new CliError("provider_unavailable", "another sync or knowledge operation holds this profile's lock; retry later");
|
|
26
|
+
throw new CliError("provider_unavailable", "another sync or knowledge operation holds this profile's lock; retry later", { reason: "profile.locked" });
|
|
25
27
|
}
|
|
26
28
|
};
|
|
27
29
|
//# sourceMappingURL=profile-lock.js.map
|
package/dist/profile-lock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-lock.js","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,QAAQ,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAsB,EAAE,IAAY,EAAE,EAAE;IACxE,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC3B,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;YACzD,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,CAAC;YACV,aAAa,EAAE,GAAG,EAAE;gBAClB,WAAW,GAAG,IAAI,CAAA;YACpB,CAAC;SACF,CAAC,CAAA;QACF,OAAO;YACL,OAAO;YACP,UAAU,EAAE,GAAG,EAAE;gBACf,IAAI,WAAW;
|
|
1
|
+
{"version":3,"file":"profile-lock.js","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,QAAQ,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAsB,EAAE,IAAY,EAAE,EAAE;IACxE,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC3B,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;YACzD,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,CAAC;YACV,aAAa,EAAE,GAAG,EAAE;gBAClB,WAAW,GAAG,IAAI,CAAA;YACpB,CAAC;SACF,CAAC,CAAA;QACF,OAAO;YACL,OAAO;YACP,UAAU,EAAE,GAAG,EAAE;gBACf,IAAI,WAAW;oBACb,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,4CAA4C,EAAE;wBACvF,MAAM,EAAE,gBAAgB;qBACzB,CAAC,CAAA;YACN,CAAC;SACF,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAChB,sBAAsB,EACtB,4EAA4E,EAC5E,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAC7B,CAAA;IACH,CAAC;AACH,CAAC,CAAA"}
|
package/dist/program.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,YAAY,EAEjB,KAAK,OAAO,EAEb,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAAE,OAAO,EAAsC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,YAAY,EAEjB,KAAK,OAAO,EAEb,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAAE,OAAO,EAAsC,MAAM,WAAW,CAAA;AAgBvE,OAAO,EAAE,KAAK,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAAa,KAAK,SAAS,EAAa,MAAM,iBAAiB,CAAA;AAGtE,OAAO,EAAE,KAAK,aAAa,EAAU,KAAK,YAAY,EAA0B,MAAM,YAAY,CAAA;AAYlG,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IACnD,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACpC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,CAAA;CAC7C;AAWD,eAAO,MAAM,aAAa,aAAa,cAAc,KAAQ,OAqsB5D,CAAA"}
|
package/dist/program.js
CHANGED
|
@@ -2,17 +2,19 @@ import { readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { CliError, createDeadline, createOutputBuffer, createRenderer, processStreams, visibleControls, } from "@wirecat/cli-base";
|
|
3
3
|
import { annotate, describeOptions, flatten, metaOf } from "@wirecat/cli-base/commands";
|
|
4
4
|
import { formatSuggestions, suggest } from "@wirecat/cli-base/completion";
|
|
5
|
-
import { commandWords, liftProfile, parseDuration, refuseCommandName } from "@wirecat/cli-
|
|
5
|
+
import { commandWords, liftProfile, parseDuration, refuseCommandName } from "@wirecat/cli-core/cli";
|
|
6
6
|
import { Command, Help, InvalidArgumentError, Option } from "commander";
|
|
7
7
|
import { validateRequest } from "./api-contract.js";
|
|
8
|
-
import {
|
|
8
|
+
import { installCatalogCommands } from "./catalog-commands.js";
|
|
9
|
+
import { activeProfile, application, checkTextLimit, configKey, fileId, pictureSearch, profileName, readConfig, SETTING_NAMES, writeConfig, } from "./config.js";
|
|
9
10
|
import { googleError } from "./errors.js";
|
|
10
11
|
import { memoryModel } from "./extraction.js";
|
|
11
|
-
import { googleSource } from "./google.js";
|
|
12
|
+
import { googleSource, MAX_ENTRIES } from "./google.js";
|
|
12
13
|
import { apiMethod, googleApi } from "./google-api.js";
|
|
13
14
|
import { installKnowledgeCommands } from "./knowledge-commands.js";
|
|
14
15
|
import { login } from "./login.js";
|
|
15
|
-
import { FOLDER } from "./model.js";
|
|
16
|
+
import { FOLDER, metadataJson, skipJson } from "./model.js";
|
|
17
|
+
import { answerOf } from "./output.js";
|
|
16
18
|
import { checkPolicy, guardedGoogleWrite, methodPolicyKeys } from "./policy.js";
|
|
17
19
|
import { lockProfile } from "./profile-lock.js";
|
|
18
20
|
import { ACCOUNT_FREE_COMMANDS, commandsDocument, describeDriveProgram, examples } from "./registry.js";
|
|
@@ -35,6 +37,7 @@ const offset = (input) => {
|
|
|
35
37
|
return n;
|
|
36
38
|
};
|
|
37
39
|
export const createProgram = (options = {}) => {
|
|
40
|
+
const startedAt = Date.now();
|
|
38
41
|
const env = options.env ?? process.env;
|
|
39
42
|
const streams = options.streams ?? processStreams;
|
|
40
43
|
const program = new Command("drive")
|
|
@@ -46,6 +49,7 @@ export const createProgram = (options = {}) => {
|
|
|
46
49
|
.option("--jsonl", "print machine-readable JSON lines")
|
|
47
50
|
.option("--agent-json", "show control and direction characters visibly in machine output")
|
|
48
51
|
.option("--quiet", "suppress optional diagnostics")
|
|
52
|
+
.option("--debug", "on failure, show the full error record: cause and stack")
|
|
49
53
|
.option("--timeout <duration>", "whole-command deadline, e.g. 30s", (raw) => parseDuration(raw, "--timeout"))
|
|
50
54
|
.option("--max-output-bytes <n>", "largest result to print, in bytes; 0 for no limit", offset, 4 * 1024 * 1024)
|
|
51
55
|
.option("--read-only", "refuse local and remote mutations")
|
|
@@ -68,7 +72,7 @@ export const createProgram = (options = {}) => {
|
|
|
68
72
|
throw new CliError("validation_error", "choose a profile explicitly: drive <profile> <command> or drive --profile <name> <command>; " +
|
|
69
73
|
(choices.length
|
|
70
74
|
? `configured profiles: ${choices.join(", ")}`
|
|
71
|
-
: "no profiles configured; connect with drive personal session start"), { profiles: choices });
|
|
75
|
+
: "no profiles configured; connect with drive personal session start"), { reason: "profile.required", profiles: choices });
|
|
72
76
|
}
|
|
73
77
|
return profileName(name);
|
|
74
78
|
};
|
|
@@ -98,6 +102,7 @@ export const createProgram = (options = {}) => {
|
|
|
98
102
|
return value;
|
|
99
103
|
};
|
|
100
104
|
const output = (value) => {
|
|
105
|
+
const result = currentAction?.name() === "commands" ? value : answerOf(value, { startedAt, limit: currentAction?.opts().limit });
|
|
101
106
|
const buffer = createOutputBuffer({ maxOutputBytes: program.opts().maxOutputBytes });
|
|
102
107
|
createRenderer({
|
|
103
108
|
format: program.opts().jsonl
|
|
@@ -108,7 +113,7 @@ export const createProgram = (options = {}) => {
|
|
|
108
113
|
color: false,
|
|
109
114
|
streams: { ...streams, data: (text) => buffer.data(text) },
|
|
110
115
|
quiet: program.opts().quiet === true,
|
|
111
|
-
}).result(program.opts().agentJson ? safeForAgent(
|
|
116
|
+
}).result(program.opts().agentJson ? safeForAgent(result) : result);
|
|
112
117
|
buffer.flush((text) => streams.data(text));
|
|
113
118
|
};
|
|
114
119
|
const source = async () => {
|
|
@@ -159,7 +164,7 @@ export const createProgram = (options = {}) => {
|
|
|
159
164
|
scope: "all-configured-profiles",
|
|
160
165
|
items: Object.entries(readConfig(env).profiles).map(([name, p]) => ({
|
|
161
166
|
profile: name,
|
|
162
|
-
|
|
167
|
+
selected_folders: p.roots.length,
|
|
163
168
|
storage: p.storage,
|
|
164
169
|
})),
|
|
165
170
|
}));
|
|
@@ -172,7 +177,7 @@ export const createProgram = (options = {}) => {
|
|
|
172
177
|
credentials(env, profile.storage, options.keyring).remove(name);
|
|
173
178
|
// Preserve the principal and roots so reauthorization resumes the same source identities.
|
|
174
179
|
writeConfig(env, config);
|
|
175
|
-
output({ profile: name,
|
|
180
|
+
output({ profile: name, signed_out: true, cached_data: "retained" });
|
|
176
181
|
});
|
|
177
182
|
const folders = program.command("folders").description("choose the Google Drive folders that sync imports");
|
|
178
183
|
const folderArgument = "folder id or Google Drive URL";
|
|
@@ -209,7 +214,11 @@ export const createProgram = (options = {}) => {
|
|
|
209
214
|
writeConfig(env, config);
|
|
210
215
|
output({ id, removed: true, next: `run drive ${name} sync to reconcile cached sources` });
|
|
211
216
|
});
|
|
212
|
-
examples(program
|
|
217
|
+
examples(program
|
|
218
|
+
.command("sync")
|
|
219
|
+
.summary("import what changed in the chosen folders, and finish an unfinished sync")
|
|
220
|
+
.description("import what changed in the chosen folders, and finish an unfinished sync; " +
|
|
221
|
+
`one sync reads at most ${MAX_ENTRIES} entries under the chosen folders, and as many changes`), ["drive personal sync", "drive personal sync --rescan --limit 500"])
|
|
213
222
|
.option("--limit <n>", "how many documents to read from Google in this run", positive, 200)
|
|
214
223
|
.option("--rescan", "read every chosen folder again instead of only what changed")
|
|
215
224
|
.option("--embed", "also index pending text for meaning search, with a model already downloaded")
|
|
@@ -223,7 +232,9 @@ export const createProgram = (options = {}) => {
|
|
|
223
232
|
if (result.errors.length || result.pending)
|
|
224
233
|
streams.diagnostic(`${result.pending} source operations remain; run drive ${selected()} sync again\n`);
|
|
225
234
|
if (result.errors.length)
|
|
226
|
-
throw new CliError("provider_error", "sync completed partially; failed operations remain pending"
|
|
235
|
+
throw new CliError("provider_error", "sync completed partially; failed operations remain pending", {
|
|
236
|
+
reason: "sync.partial",
|
|
237
|
+
});
|
|
227
238
|
});
|
|
228
239
|
examples(program.command("status").description("show the last sync, imported documents and pending work"), [
|
|
229
240
|
"drive personal status",
|
|
@@ -233,13 +244,13 @@ export const createProgram = (options = {}) => {
|
|
|
233
244
|
const state = readState(env, name, profile.principal);
|
|
234
245
|
output({
|
|
235
246
|
profile: name,
|
|
236
|
-
|
|
247
|
+
selected_folders: profile.roots,
|
|
237
248
|
documents: Object.keys(state.documents).length,
|
|
238
249
|
pending: state.pending?.jobs.length ?? 0,
|
|
239
|
-
skipped: state.skipped,
|
|
240
|
-
|
|
250
|
+
skipped: state.skipped.map(skipJson),
|
|
251
|
+
last_sync: state.lastSync ?? null,
|
|
241
252
|
coverage: "Google Docs and Markdown/TXT; native export tab fidelity and assets are not verified",
|
|
242
|
-
|
|
253
|
+
remote_checked: false,
|
|
243
254
|
});
|
|
244
255
|
});
|
|
245
256
|
const documents = program.command("documents").description("read imported documents and Google Docs");
|
|
@@ -266,7 +277,7 @@ export const createProgram = (options = {}) => {
|
|
|
266
277
|
});
|
|
267
278
|
output({
|
|
268
279
|
items: docs.map((doc) => ({
|
|
269
|
-
...doc.metadata,
|
|
280
|
+
...metadataJson(doc.metadata),
|
|
270
281
|
reference: doc.reference,
|
|
271
282
|
tabs: doc.tabs,
|
|
272
283
|
})),
|
|
@@ -277,7 +288,9 @@ export const createProgram = (options = {}) => {
|
|
|
277
288
|
const profile = activeProfile(env, selected());
|
|
278
289
|
const state = readState(env, selected(), profile.principal);
|
|
279
290
|
if (!state.documents[id])
|
|
280
|
-
throw new CliError("not_found", "this source is not imported in the selected profile"
|
|
291
|
+
throw new CliError("not_found", "this source is not imported in the selected profile", {
|
|
292
|
+
reason: "document.not-imported",
|
|
293
|
+
});
|
|
281
294
|
const doc = state.documents[id];
|
|
282
295
|
return { id, ref: doc.reference, hash: doc.hash, snapshot: readSnapshot(env, selected(), id) };
|
|
283
296
|
};
|
|
@@ -286,7 +299,12 @@ export const createProgram = (options = {}) => {
|
|
|
286
299
|
.argument("<document>", documentArgument)
|
|
287
300
|
.description("show an imported document's text, tabs and metadata"), ["drive personal documents show DOC_ID"]).action((input) => {
|
|
288
301
|
const { snapshot } = imported(input);
|
|
289
|
-
output({
|
|
302
|
+
output({
|
|
303
|
+
metadata: metadataJson(snapshot.metadata),
|
|
304
|
+
text: snapshot.text,
|
|
305
|
+
tabs: snapshot.tabs,
|
|
306
|
+
...(snapshot.notRead ? { not_read: snapshot.notRead } : {}),
|
|
307
|
+
});
|
|
290
308
|
});
|
|
291
309
|
examples(documents
|
|
292
310
|
.command("export")
|
|
@@ -295,7 +313,17 @@ export const createProgram = (options = {}) => {
|
|
|
295
313
|
.requiredOption("--out <file>", "path of the Markdown file to write; an existing file is refused")
|
|
296
314
|
.action((input, args) => {
|
|
297
315
|
const { id, snapshot } = imported(input);
|
|
298
|
-
|
|
316
|
+
try {
|
|
317
|
+
writeFileSync(args.out, snapshot.markdown, { flag: "wx", mode: 0o600 });
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (error.code === "EEXIST")
|
|
321
|
+
throw new CliError("validation_error", "the output file already exists; choose another --out", {
|
|
322
|
+
reason: "export.exists",
|
|
323
|
+
param: "--out",
|
|
324
|
+
});
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
299
327
|
output({ id, path: args.out, format: "markdown" });
|
|
300
328
|
});
|
|
301
329
|
examples(program
|
|
@@ -305,7 +333,12 @@ export const createProgram = (options = {}) => {
|
|
|
305
333
|
.option("--limit <n>", "how many results to return", positive, 20)
|
|
306
334
|
.option("--offset <n>", "how many results to skip", offset, 0)
|
|
307
335
|
.option("--exact", "match the words exactly: no word forms, no meaning")
|
|
308
|
-
.action(async (query, args) => output(await withIndex((index) => index.search(activeProfile(env, selected()).principal, query, {
|
|
336
|
+
.action(async (query, args) => output(await withIndex((index) => index.search(activeProfile(env, selected()).principal, query, {
|
|
337
|
+
...args,
|
|
338
|
+
exact: args.exact ?? false,
|
|
339
|
+
...(pictureSearch(env, selected()) ? { pictures: true } : {}),
|
|
340
|
+
}))));
|
|
341
|
+
installCatalogCommands(program, { env, selected, output, positive, offset, withIndex });
|
|
309
342
|
installKnowledgeCommands(program, {
|
|
310
343
|
document: imported,
|
|
311
344
|
output,
|
|
@@ -315,12 +348,14 @@ export const createProgram = (options = {}) => {
|
|
|
315
348
|
run: async (input, fn) => {
|
|
316
349
|
const lock = await lockProfile(env, selected());
|
|
317
350
|
try {
|
|
318
|
-
const { ref } = imported(input);
|
|
319
351
|
return await withIndex(async (index) => {
|
|
320
352
|
lock.assertHeld();
|
|
321
353
|
if (!index.knowledge)
|
|
322
354
|
throw new CliError("configuration_error", "index has no shared knowledge adapter");
|
|
323
|
-
const
|
|
355
|
+
const principal = activeProfile(env, selected()).principal;
|
|
356
|
+
const found = await index.catalog?.get(principal, fileId(input));
|
|
357
|
+
const ref = found?.ref ?? imported(input).ref;
|
|
358
|
+
const result = await fn(index.knowledge, principal, ref);
|
|
324
359
|
lock.assertHeld();
|
|
325
360
|
return result;
|
|
326
361
|
});
|
|
@@ -333,7 +368,18 @@ export const createProgram = (options = {}) => {
|
|
|
333
368
|
installRemoteCommands(program, {
|
|
334
369
|
output,
|
|
335
370
|
positive,
|
|
336
|
-
readBody: options.readBody ??
|
|
371
|
+
readBody: options.readBody ??
|
|
372
|
+
((path) => {
|
|
373
|
+
try {
|
|
374
|
+
return readFileSync(path, "utf8");
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
throw new CliError("validation_error", "the request body file could not be read", {
|
|
378
|
+
reason: "body.unreadable",
|
|
379
|
+
param: "--body-file",
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}),
|
|
337
383
|
call: async (method, params, body) => {
|
|
338
384
|
const descriptor = apiMethod(method);
|
|
339
385
|
validateRequest(method, params, body);
|
|
@@ -341,14 +387,16 @@ export const createProgram = (options = {}) => {
|
|
|
341
387
|
for (const key of methodPolicyKeys(method))
|
|
342
388
|
await checkPolicy(env, selected(), key, descriptor.mutates, flags, askOnce);
|
|
343
389
|
if (flags.offline)
|
|
344
|
-
throw new CliError("permission_error", "this operation needs Google; --offline was requested"
|
|
390
|
+
throw new CliError("permission_error", "this operation needs Google; --offline was requested", {
|
|
391
|
+
reason: "offline.refused",
|
|
392
|
+
});
|
|
345
393
|
if (flags.dryRun)
|
|
346
394
|
return {
|
|
347
|
-
|
|
395
|
+
dry_run: true,
|
|
348
396
|
method,
|
|
349
397
|
mutates: descriptor.mutates,
|
|
350
398
|
parameters: params,
|
|
351
|
-
|
|
399
|
+
body_provided: body !== undefined,
|
|
352
400
|
};
|
|
353
401
|
const act = async () => {
|
|
354
402
|
try {
|
|
@@ -370,13 +418,14 @@ export const createProgram = (options = {}) => {
|
|
|
370
418
|
"drive personal config show",
|
|
371
419
|
]).action(() => output(readConfig(env)));
|
|
372
420
|
examples(config.command("set").description("set one setting of this profile, or of the defaults"), [
|
|
373
|
-
"drive personal config set
|
|
421
|
+
"drive personal config set read_only true",
|
|
374
422
|
`drive personal config set permissions.files '"readonly"' --defaults`,
|
|
375
423
|
])
|
|
376
|
-
.argument("<key>", "
|
|
424
|
+
.argument("<key>", "read_only, max_text_chars, picture_search, shared AI settings, permissions.<key> or models.<purpose>.<field>")
|
|
377
425
|
.argument("<json-value>", "the new value, as JSON")
|
|
378
426
|
.option("--defaults", "change the defaults instead of this profile")
|
|
379
|
-
.action((
|
|
427
|
+
.action((rawKey, raw, args) => {
|
|
428
|
+
const key = configKey(rawKey);
|
|
380
429
|
const value = readConfig(env);
|
|
381
430
|
if (args.defaults)
|
|
382
431
|
value.defaults ??= {};
|
|
@@ -386,9 +435,9 @@ export const createProgram = (options = {}) => {
|
|
|
386
435
|
if (!args.defaults)
|
|
387
436
|
value.profiles[selected()] = target;
|
|
388
437
|
const [head, ...parts] = key.split(".");
|
|
389
|
-
if (!
|
|
438
|
+
if (!SETTING_NAMES.has(head ?? "") ||
|
|
390
439
|
parts.some((part) => ["__proto__", "prototype", "constructor"].includes(part)))
|
|
391
|
-
throw new CliError("validation_error", "config set accepts
|
|
440
|
+
throw new CliError("validation_error", "config set accepts profile settings and shared AI settings");
|
|
392
441
|
let parsed;
|
|
393
442
|
try {
|
|
394
443
|
parsed = JSON.parse(raw);
|
|
@@ -396,8 +445,13 @@ export const createProgram = (options = {}) => {
|
|
|
396
445
|
catch {
|
|
397
446
|
throw new CliError("validation_error", "setting value must be JSON");
|
|
398
447
|
}
|
|
399
|
-
if (head === "
|
|
400
|
-
|
|
448
|
+
if (head === "picture_search") {
|
|
449
|
+
if (args.defaults || parts.length || typeof parsed !== "boolean")
|
|
450
|
+
throw new CliError("validation_error", "picture_search is true or false, set per profile");
|
|
451
|
+
target.picture_search = parsed;
|
|
452
|
+
}
|
|
453
|
+
else if (head === "max_text_chars" && !parts.length)
|
|
454
|
+
target.max_text_chars = checkTextLimit(parsed);
|
|
401
455
|
else if (!parts.length)
|
|
402
456
|
Object.assign(target, { [key]: parsed });
|
|
403
457
|
else if (head === "permissions") {
|
|
@@ -448,7 +502,7 @@ export const createProgram = (options = {}) => {
|
|
|
448
502
|
config.defaults.models[args.purpose] = {
|
|
449
503
|
provider: args.provider,
|
|
450
504
|
...(args.model ? { model: args.model } : {}),
|
|
451
|
-
...(args.baseUrl ? {
|
|
505
|
+
...(args.baseUrl ? { base_url: args.baseUrl } : {}),
|
|
452
506
|
};
|
|
453
507
|
writeConfig(env, config);
|
|
454
508
|
output({ purpose: args.purpose, configured: true });
|
|
@@ -465,7 +519,7 @@ export const createProgram = (options = {}) => {
|
|
|
465
519
|
output({
|
|
466
520
|
items: mcpTools({ ...options, env }, selected(), policyFlags()).map(({ name, schema, command }) => ({
|
|
467
521
|
name,
|
|
468
|
-
|
|
522
|
+
input_schema: schema,
|
|
469
523
|
mutates: command.mutates,
|
|
470
524
|
})),
|
|
471
525
|
});
|
|
@@ -521,7 +575,8 @@ export const createProgram = (options = {}) => {
|
|
|
521
575
|
annotate(command, {
|
|
522
576
|
origin: metaOf(command).origin ?? "handwritten",
|
|
523
577
|
mutates: metaOf(command).mutates ?? (localWrites.includes(name) || remoteWrites.includes(name)),
|
|
524
|
-
local:
|
|
578
|
+
local: metaOf(command).local ??
|
|
579
|
+
(localWrites.includes(name) && name !== "session start" && name !== "memories extract"),
|
|
525
580
|
state: "beta",
|
|
526
581
|
});
|
|
527
582
|
}
|
|
@@ -553,13 +608,15 @@ export const createProgram = (options = {}) => {
|
|
|
553
608
|
const flags = policyFlags();
|
|
554
609
|
const metadata = metaOf(action);
|
|
555
610
|
const rawMethod = words === "api call" ? action.args[0] : undefined;
|
|
556
|
-
const method = metadata.
|
|
611
|
+
const method = metadata.operation_id ?? rawMethod;
|
|
557
612
|
if (rawMethod) {
|
|
558
613
|
const descriptor = apiMethod(rawMethod);
|
|
559
614
|
if (descriptor.mutates && !action.opts().allowWrite)
|
|
560
|
-
throw new CliError("permission_error", "this method changes Google data; pass --allow-write"
|
|
615
|
+
throw new CliError("permission_error", "this method changes Google data; pass --allow-write", {
|
|
616
|
+
reason: "write.not-allowed",
|
|
617
|
+
});
|
|
561
618
|
if (descriptor.destructive && !action.opts().allowDelete && !flags.allowDangerous)
|
|
562
|
-
throw new CliError("permission_error", "this method deletes Google data; pass --allow-delete or --allow-dangerous");
|
|
619
|
+
throw new CliError("permission_error", "this method deletes Google data; pass --allow-delete or --allow-dangerous", { reason: "delete.not-allowed" });
|
|
563
620
|
if (flags.allowDangerous)
|
|
564
621
|
action.setOptionValue("allowDelete", true);
|
|
565
622
|
}
|
|
@@ -580,12 +637,14 @@ export const createProgram = (options = {}) => {
|
|
|
580
637
|
"memories extract",
|
|
581
638
|
"sync",
|
|
582
639
|
].includes(words)))
|
|
583
|
-
throw new CliError("permission_error", "this command may require network access; --offline was requested"
|
|
640
|
+
throw new CliError("permission_error", "this command may require network access; --offline was requested", {
|
|
641
|
+
reason: "offline.refused",
|
|
642
|
+
});
|
|
584
643
|
if (flags.dryRun &&
|
|
585
644
|
path[0] !== "api" &&
|
|
586
645
|
!["files", "comments", "permissions", "revisions", "shared-drives"].includes(path[0] ?? "") &&
|
|
587
646
|
!["documents get", "documents create", "documents update", "documents history"].includes(words)) {
|
|
588
|
-
output({
|
|
647
|
+
output({ dry_run: true, command: words, mutates, local: metadata.local === true });
|
|
589
648
|
throw new Preview();
|
|
590
649
|
}
|
|
591
650
|
if (words === "session start")
|