@liquidmetal-ai/raindrop 0.4.1 → 0.4.2

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.
@@ -0,0 +1,142 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { parseMRN } from '@liquidmetal-ai/drizzle/mrn';
4
+ import { create } from '@bufbuild/protobuf';
5
+ import { GetAnnotationRequestSchema, AnnotationLocatorSchema } from '@liquidmetal-ai/protogen2/annotation_pb';
6
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
7
+ export default class AnnotationGet extends BaseCommand {
8
+ static args = {
9
+ mrn: Args.string({
10
+ description: 'MRN (Machine Resource Name) of the annotation to retrieve. Can be partial (e.g., my-module:my-key:) or full (e.g., annotation:app:v1:my-module:my-key:)',
11
+ required: true,
12
+ }),
13
+ };
14
+ static description = 'Get an annotation by MRN';
15
+ static examples = [
16
+ `<%= config.bin %> annotation get my-module:my-item^my-key:
17
+ Get annotation by partial MRN (prefilled with app/version from manifest and config)
18
+ `,
19
+ `<%= config.bin %> annotation get annotation:my-app:v1.0.0:my-module:my-item^my-key:
20
+ Get annotation with the full MRN
21
+ `,
22
+ `<%= config.bin %> annotation get my-module:my-key: --format json
23
+ Get annotation by partial MRN and output as JSON
24
+ `,
25
+ ];
26
+ static flags = {
27
+ ...BaseCommand.HIDDEN_FLAGS,
28
+ format: Flags.string({
29
+ char: 'f',
30
+ description: 'output format',
31
+ default: 'text',
32
+ options: ['text', 'json'],
33
+ }),
34
+ impersonate: Flags.string({
35
+ char: 'i',
36
+ description: 'impersonate organization',
37
+ required: false,
38
+ hidden: true,
39
+ }),
40
+ manifest: Flags.string({
41
+ char: 'M',
42
+ description: 'project manifest',
43
+ required: false,
44
+ default: 'raindrop.manifest',
45
+ hidden: true,
46
+ }),
47
+ };
48
+ async run() {
49
+ const { args, flags } = await this.parse(AnnotationGet);
50
+ // Determine if we need to prefill MRN with manifest/config data
51
+ let fullMrn = args.mrn;
52
+ let mrnParts;
53
+ if (!args.mrn.startsWith('annotation:') && !args.mrn.startsWith('label:')) {
54
+ // Partial MRN - need to prefill with app name and version from manifest/config
55
+ const apps = await this.loadManifest();
56
+ const config = await this.loadConfig();
57
+ if (apps.length === 0) {
58
+ this.error('No applications found in manifest');
59
+ }
60
+ const app = apps[0];
61
+ const appName = valueOf(app.name);
62
+ const versionId = config.versionId;
63
+ console.log(`Using application: ${appName}, version: ${versionId}`);
64
+ if (!appName) {
65
+ this.error('Application name not found in manifest');
66
+ }
67
+ if (!versionId) {
68
+ this.error('Version ID not found in config. Run a build or deployment first to set the version.');
69
+ }
70
+ fullMrn = `annotation:${appName}:${versionId}:${args.mrn}`;
71
+ }
72
+ // Auto-fill trailing colons if there are fewer than 6 parts in the MRN
73
+ const parts = fullMrn.split(':');
74
+ // A complete annotation MRN has 6 parts (annotation:app:version:module:item:revision)
75
+ if (parts.length < 6) {
76
+ // Add as many colons as needed to get to 6 parts
77
+ const colonsToAdd = 6 - parts.length;
78
+ fullMrn += ':'.repeat(colonsToAdd);
79
+ }
80
+ // Parse MRN to extract components using the common library
81
+ try {
82
+ mrnParts = parseMRN(fullMrn);
83
+ }
84
+ catch (error) {
85
+ this.error(`Invalid MRN format: ${error}`);
86
+ }
87
+ // Get annotation service client
88
+ const { client: annotationServiceClient, userId, organizationId, } = await this.annotationService(mrnParts.applicationName, mrnParts.versionId);
89
+ try {
90
+ // Create annotation locator from MRN parts
91
+ const locator = create(AnnotationLocatorSchema, {
92
+ applicationName: mrnParts.applicationName,
93
+ applicationVersionId: mrnParts.versionId,
94
+ moduleName: mrnParts.module,
95
+ item: mrnParts.item,
96
+ key: mrnParts.key,
97
+ revision: mrnParts.revision,
98
+ });
99
+ // Call the annotation service
100
+ const request = create(GetAnnotationRequestSchema, {
101
+ userId,
102
+ organizationId,
103
+ locator,
104
+ });
105
+ const response = await annotationServiceClient.getAnnotation(request);
106
+ switch (flags.format) {
107
+ case 'json':
108
+ console.log(JSON.stringify({
109
+ mrn: fullMrn,
110
+ inputMrn: args.mrn,
111
+ ...mrnParts,
112
+ annotation: response.annotation?.annotation || '',
113
+ location: response.annotation?.location,
114
+ }, null, 2));
115
+ break;
116
+ case 'text':
117
+ console.log(`MRN: ${fullMrn}`);
118
+ if (fullMrn !== args.mrn) {
119
+ console.log(`Input: ${args.mrn} (prefilled with app/version)`);
120
+ }
121
+ console.log(`Type: ${mrnParts.type}`);
122
+ console.log(`Application: ${mrnParts.applicationName}`);
123
+ console.log(`Version: ${mrnParts.versionId}`);
124
+ if (mrnParts.module)
125
+ console.log(`Module: ${mrnParts.module}`);
126
+ if (mrnParts.item)
127
+ console.log(`Item: ${mrnParts.item}`);
128
+ if (mrnParts.key)
129
+ console.log(`Key: ${mrnParts.key}`);
130
+ if (mrnParts.revision)
131
+ console.log(`Revision: ${mrnParts.revision}`);
132
+ console.log('');
133
+ console.log('Annotation:');
134
+ console.log(response.annotation?.annotation || '(no content)');
135
+ break;
136
+ }
137
+ }
138
+ catch (error) {
139
+ this.error(`Failed to get annotation: ${error}`);
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,23 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class AnnotationList extends BaseCommand<typeof AnnotationList> {
3
+ static args: {
4
+ mrnPrefix: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
11
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/annotation/list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOpD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,WAAW,CAAC,OAAO,cAAc,CAAC;IAC5E,MAAM,CAAC,IAAI;;MAMT;IAEF,MAAM,CAAC,WAAW,SAAoC;IAEtD,MAAM,CAAC,QAAQ,WAUb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;;MA0BV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+L3B"}
@@ -0,0 +1,223 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { parseMRN } from '@liquidmetal-ai/drizzle/mrn';
4
+ import { create } from '@bufbuild/protobuf';
5
+ import { ListAnnotationsRequestSchema, AnnotationLocatorSchema } from '@liquidmetal-ai/protogen2/annotation_pb';
6
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
7
+ export default class AnnotationList extends BaseCommand {
8
+ static args = {
9
+ mrnPrefix: Args.string({
10
+ description: 'MRN prefix to filter annotations (e.g., my-module or annotation:app:v1:my-module). If not provided, uses app/version from manifest and config.',
11
+ required: false,
12
+ }),
13
+ };
14
+ static description = 'List annotations by MRN prefix';
15
+ static examples = [
16
+ `<%= config.bin %> annotation list
17
+ List all annotations for the current app/version from manifest and config
18
+ `,
19
+ `<%= config.bin %> annotation list my-module
20
+ List annotations for 'my-module' (prefilled with app/version from manifest and config)
21
+ `,
22
+ `<%= config.bin %> annotation list annotation:my-app:v1.0.0:my-module --format json
23
+ List annotations for a specific module using full MRN prefix in JSON format
24
+ `,
25
+ ];
26
+ static flags = {
27
+ ...BaseCommand.HIDDEN_FLAGS,
28
+ output: Flags.string({
29
+ char: 'o',
30
+ description: 'output format',
31
+ default: 'table',
32
+ options: ['table', 'text', 'json'],
33
+ }),
34
+ limit: Flags.integer({
35
+ char: 'l',
36
+ description: 'maximum number of annotations to return',
37
+ default: 100,
38
+ }),
39
+ impersonate: Flags.string({
40
+ char: 'i',
41
+ description: 'impersonate organization',
42
+ required: false,
43
+ hidden: true,
44
+ }),
45
+ manifest: Flags.string({
46
+ char: 'M',
47
+ description: 'project manifest',
48
+ required: false,
49
+ default: 'raindrop.manifest',
50
+ hidden: true,
51
+ }),
52
+ };
53
+ async run() {
54
+ const { args, flags } = await this.parse(AnnotationList);
55
+ // Parse MRN prefix if provided to extract application info for service connection
56
+ let appName = '';
57
+ let versionId = '';
58
+ let mrnParts = {};
59
+ let fullMrnPrefix = args.mrnPrefix || '';
60
+ if (args.mrnPrefix) {
61
+ // Check if we need to prefill with manifest/config data
62
+ if (!args.mrnPrefix.startsWith('annotation:') && !args.mrnPrefix.startsWith('label:')) {
63
+ // Partial MRN - need to prefill with app name and version from manifest/config
64
+ const apps = await this.loadManifest();
65
+ const config = await this.loadConfig();
66
+ if (apps.length === 0) {
67
+ this.error('No applications found in manifest');
68
+ }
69
+ const app = apps[0];
70
+ const manifestAppName = valueOf(app.name);
71
+ const configVersionId = config.versionId;
72
+ if (!manifestAppName) {
73
+ this.error('Application name not found in manifest');
74
+ }
75
+ if (!configVersionId) {
76
+ this.error('Version ID not found in config. Run a build or deployment first to set the version.');
77
+ }
78
+ fullMrnPrefix = `annotation:${manifestAppName}:${configVersionId}:${args.mrnPrefix}`;
79
+ }
80
+ try {
81
+ // Try to parse as full MRN first
82
+ mrnParts = parseMRN(fullMrnPrefix);
83
+ appName = mrnParts.applicationName;
84
+ versionId = mrnParts.versionId;
85
+ }
86
+ catch {
87
+ // If it fails, try to extract at least app:version from prefix
88
+ const parts = fullMrnPrefix.split(':');
89
+ if (parts.length >= 3 && parts[0] === 'annotation') {
90
+ appName = parts[1];
91
+ versionId = parts[2];
92
+ mrnParts = {
93
+ type: parts[0],
94
+ applicationName: parts[1],
95
+ versionId: parts[2],
96
+ module: parts[3] || undefined,
97
+ key: parts[4] || undefined,
98
+ revision: parts[5] || undefined,
99
+ };
100
+ }
101
+ else {
102
+ this.error('MRN prefix must at least contain annotation:applicationName:versionId');
103
+ }
104
+ }
105
+ }
106
+ else {
107
+ // No MRN prefix provided - use manifest/config data to create default prefix
108
+ const apps = await this.loadManifest();
109
+ const config = await this.loadConfig();
110
+ if (apps.length === 0) {
111
+ this.error('No applications found in manifest');
112
+ }
113
+ const app = apps[0];
114
+ const manifestAppName = valueOf(app.name);
115
+ const configVersionId = config.versionId;
116
+ if (!manifestAppName) {
117
+ this.error('Application name not found in manifest');
118
+ }
119
+ if (!configVersionId) {
120
+ this.error('Version ID not found in config. Run a build or deployment first to set the version.');
121
+ }
122
+ appName = manifestAppName;
123
+ versionId = configVersionId;
124
+ fullMrnPrefix = `annotation:${manifestAppName}:${configVersionId}`;
125
+ mrnParts = {
126
+ type: 'annotation',
127
+ applicationName: manifestAppName,
128
+ versionId: configVersionId,
129
+ };
130
+ }
131
+ // Get annotation service client
132
+ const { client: annotationServiceClient, userId, organizationId, } = await this.annotationService(appName, versionId);
133
+ try {
134
+ // Create annotation locator from MRN parts
135
+ const locator = create(AnnotationLocatorSchema, {
136
+ applicationName: mrnParts.applicationName,
137
+ applicationVersionId: mrnParts.versionId,
138
+ moduleName: mrnParts.module,
139
+ item: mrnParts.item,
140
+ key: mrnParts.key,
141
+ revision: mrnParts.revision,
142
+ });
143
+ // Call the annotation service
144
+ const request = create(ListAnnotationsRequestSchema, {
145
+ userId,
146
+ organizationId,
147
+ locator,
148
+ });
149
+ const response = await annotationServiceClient.listAnnotations(request);
150
+ const annotations = response.annotation || [];
151
+ switch (flags.output) {
152
+ case 'json':
153
+ console.log(JSON.stringify({
154
+ annotations: annotations.map((loc) => ({
155
+ applicationName: loc.applicationName,
156
+ applicationVersionId: loc.applicationVersionId,
157
+ moduleName: loc.moduleName,
158
+ item: loc.item,
159
+ key: loc.key,
160
+ revision: loc.revision,
161
+ })),
162
+ total: annotations.length,
163
+ prefix: fullMrnPrefix,
164
+ inputPrefix: args.mrnPrefix,
165
+ }, null, 2));
166
+ break;
167
+ case 'text':
168
+ console.log(`Found ${annotations.length} annotations`);
169
+ console.log(`Prefix: ${fullMrnPrefix}`);
170
+ if (fullMrnPrefix !== (args.mrnPrefix || '')) {
171
+ console.log(`Input: ${args.mrnPrefix || '(none)'} (prefilled with app/version)`);
172
+ }
173
+ console.log('');
174
+ annotations.forEach((loc, index) => {
175
+ const mrn = `${loc.applicationName}:${loc.applicationVersionId}:${loc.moduleName || ''}:${loc.item || ''}^${loc.key || ''}:${loc.revision || ''}`;
176
+ console.log(`${index + 1}. ${mrn}`);
177
+ console.log(` Application: ${loc.applicationName}`);
178
+ console.log(` Version: ${loc.applicationVersionId}`);
179
+ if (loc.moduleName)
180
+ console.log(` Module: ${loc.moduleName}`);
181
+ if (loc.item)
182
+ console.log(` Item: ${loc.item}`);
183
+ if (loc.key)
184
+ console.log(` Key: ${loc.key}`);
185
+ if (loc.revision)
186
+ console.log(` Revision: ${loc.revision}`);
187
+ console.log('');
188
+ });
189
+ break;
190
+ case 'table':
191
+ if (annotations.length === 0) {
192
+ console.log('No annotations found');
193
+ console.log(`Prefix: ${fullMrnPrefix}`);
194
+ if (fullMrnPrefix !== (args.mrnPrefix || '')) {
195
+ console.log(`Input: ${args.mrnPrefix || '(none)'} (prefilled with app/version)`);
196
+ }
197
+ }
198
+ else {
199
+ console.log('Application Version Module Item Key Revision');
200
+ console.log('--------------- --------------- --------------- --------------- --------------- ---------------');
201
+ annotations.forEach((loc) => {
202
+ const app = (loc.applicationName || '').padEnd(15).substring(0, 15);
203
+ const version = (loc.applicationVersionId || '').padEnd(15).substring(0, 15);
204
+ const module = (loc.moduleName || '').padEnd(15).substring(0, 15);
205
+ const item = (loc.item || '').padEnd(15).substring(0, 15);
206
+ const key = (loc.key || '').padEnd(15).substring(0, 15);
207
+ const revision = (loc.revision || '').padEnd(15).substring(0, 15);
208
+ console.log(`${app} ${version} ${module} ${item} ${key} ${revision}`);
209
+ });
210
+ console.log(`\nTotal: ${annotations.length} annotations`);
211
+ console.log(`Prefix: ${fullMrnPrefix}`);
212
+ if (fullMrnPrefix !== (args.mrnPrefix || '')) {
213
+ console.log(`Input: ${args.mrnPrefix || '(none)'} (prefilled with app/version)`);
214
+ }
215
+ }
216
+ break;
217
+ }
218
+ }
219
+ catch (error) {
220
+ this.error(`Failed to list annotations: ${error}`);
221
+ }
222
+ }
223
+ }
@@ -0,0 +1,23 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class AnnotationPut extends BaseCommand<typeof AnnotationPut> {
3
+ static args: {
4
+ mrn: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ annotation: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ impersonate: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ manifest: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ config: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ rainbowAuthService: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ raindropCatalogService: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ rainbowAuthToken: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ rainbowOrganizationId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ rainbowUserId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ sendVersionMetadata: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=put.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put.d.ts","sourceRoot":"","sources":["../../../src/commands/annotation/put.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW,CAAC,OAAO,aAAa,CAAC;IAC1E,MAAM,CAAC,IAAI;;;MAUT;IAEF,MAAM,CAAC,WAAW,SAA2C;IAE7D,MAAM,CAAC,QAAQ,WAUb;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;;MAqBV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAyI3B"}
@@ -0,0 +1,172 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { parseMRN } from '@liquidmetal-ai/drizzle/mrn';
4
+ import { create } from '@bufbuild/protobuf';
5
+ import { PutAnnotationRequestSchema, AnnotationLocatorSchema } from '@liquidmetal-ai/protogen2/annotation_pb';
6
+ import * as fs from 'node:fs/promises';
7
+ import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
8
+ export default class AnnotationPut extends BaseCommand {
9
+ static args = {
10
+ mrn: Args.string({
11
+ description: 'MRN (Machine Resource Name) of the annotation to create/update. Can be partial (e.g., my-module:my-key:) or full (e.g., annotation:app:v1:my-module:my-key:)',
12
+ required: true,
13
+ }),
14
+ annotation: Args.string({
15
+ description: 'annotation content (use "-" to read from stdin)',
16
+ required: true,
17
+ }),
18
+ };
19
+ static description = 'Create or update an annotation by MRN';
20
+ static examples = [
21
+ `<%= config.bin %> annotation put my-module:my-key: "This is my annotation"
22
+ Create an annotation with partial MRN (prefilled with app/version from manifest and config)
23
+ `,
24
+ `<%= config.bin %> annotation put annotation:my-app:v1.0.0:my-module:my-item^my-key: @file.txt
25
+ Create an annotation from file contents using full MRN
26
+ `,
27
+ `<%= config.bin %> annotation put my-module:my-key: - < input.txt
28
+ Create an annotation from stdin using partial MRN
29
+ `,
30
+ ];
31
+ static flags = {
32
+ ...BaseCommand.HIDDEN_FLAGS,
33
+ output: Flags.string({
34
+ char: 'o',
35
+ description: 'output format',
36
+ default: 'text',
37
+ options: ['text', 'json'],
38
+ }),
39
+ impersonate: Flags.string({
40
+ char: 'i',
41
+ description: 'impersonate organization',
42
+ required: false,
43
+ hidden: true,
44
+ }),
45
+ manifest: Flags.string({
46
+ char: 'M',
47
+ description: 'project manifest',
48
+ required: false,
49
+ default: 'raindrop.manifest',
50
+ hidden: true,
51
+ }),
52
+ };
53
+ async run() {
54
+ const { args, flags } = await this.parse(AnnotationPut);
55
+ // Determine if we need to prefill MRN with manifest/config data
56
+ let fullMrn = args.mrn;
57
+ let mrnParts;
58
+ if (!args.mrn.startsWith('annotation:') && !args.mrn.startsWith('label:')) {
59
+ // Partial MRN - need to prefill with app name and version from manifest/config
60
+ const apps = await this.loadManifest();
61
+ const config = await this.loadConfig();
62
+ if (apps.length === 0) {
63
+ this.error('No applications found in manifest');
64
+ }
65
+ const app = apps[0];
66
+ const appName = valueOf(app.name);
67
+ const versionId = config.versionId;
68
+ if (!appName) {
69
+ this.error('Application name not found in manifest');
70
+ }
71
+ if (!versionId) {
72
+ this.error('Version ID not found in config. Run a build or deployment first to set the version.');
73
+ }
74
+ fullMrn = `annotation:${appName}:${versionId}:${args.mrn}`;
75
+ }
76
+ // Auto-fill trailing colons if there are fewer than 6 parts in the MRN
77
+ const parts = fullMrn.split(':');
78
+ // A complete annotation MRN has 6 parts (annotation:app:version:module:item:revision)
79
+ if (parts.length < 6) {
80
+ // Add as many colons as needed to get to 6 parts
81
+ const colonsToAdd = 6 - parts.length;
82
+ fullMrn += ':'.repeat(colonsToAdd);
83
+ }
84
+ // Parse MRN to extract components using the common library
85
+ try {
86
+ mrnParts = parseMRN(fullMrn);
87
+ }
88
+ catch (error) {
89
+ this.error(`Invalid MRN format: ${error}`);
90
+ }
91
+ // Handle different input sources
92
+ let annotationContent;
93
+ if (args.annotation === '-') {
94
+ // Read from stdin
95
+ const chunks = [];
96
+ for await (const chunk of process.stdin) {
97
+ chunks.push(chunk);
98
+ }
99
+ annotationContent = Buffer.concat(chunks).toString('utf8').trim();
100
+ }
101
+ else if (args.annotation.startsWith('@')) {
102
+ // Read from file
103
+ const filePath = args.annotation.slice(1);
104
+ try {
105
+ annotationContent = await fs.readFile(filePath, 'utf8');
106
+ }
107
+ catch (error) {
108
+ this.error(`Failed to read file "${filePath}": ${error}`);
109
+ }
110
+ }
111
+ else {
112
+ // Use as literal content
113
+ annotationContent = args.annotation;
114
+ }
115
+ if (!annotationContent.trim()) {
116
+ this.error('Annotation content cannot be empty');
117
+ }
118
+ // Get annotation service client
119
+ const { client: annotationServiceClient, userId, organizationId, } = await this.annotationService(mrnParts.applicationName, mrnParts.versionId);
120
+ try {
121
+ // Create annotation locator from MRN parts
122
+ const locator = create(AnnotationLocatorSchema, {
123
+ applicationName: mrnParts.applicationName,
124
+ applicationVersionId: mrnParts.versionId,
125
+ moduleName: mrnParts.module,
126
+ item: mrnParts.item,
127
+ key: mrnParts.key,
128
+ revision: mrnParts.revision,
129
+ });
130
+ // Call the annotation service
131
+ const request = create(PutAnnotationRequestSchema, {
132
+ userId,
133
+ organizationId,
134
+ locator,
135
+ annotation: annotationContent,
136
+ });
137
+ const response = await annotationServiceClient.putAnnotation(request);
138
+ switch (flags.output) {
139
+ case 'json':
140
+ console.log(JSON.stringify({
141
+ mrn: fullMrn,
142
+ inputMrn: args.mrn,
143
+ ...mrnParts,
144
+ annotation: annotationContent,
145
+ locator: response.locator,
146
+ success: true,
147
+ }, null, 2));
148
+ break;
149
+ case 'text':
150
+ console.log(`Successfully created/updated annotation for MRN: ${fullMrn}`);
151
+ if (fullMrn !== args.mrn) {
152
+ console.log(`Input: ${args.mrn} (prefilled with app/version)`);
153
+ }
154
+ console.log(`Content length: ${annotationContent.length} characters`);
155
+ console.log(`Type: ${mrnParts.type}`);
156
+ console.log(`Application: ${mrnParts.applicationName}`);
157
+ console.log(`Version: ${mrnParts.versionId}`);
158
+ if (mrnParts.module)
159
+ console.log(`Module: ${mrnParts.module}`);
160
+ if (mrnParts.item)
161
+ console.log(`Item: ${mrnParts.item}`);
162
+ if (mrnParts.key)
163
+ console.log(`Key: ${mrnParts.key}`);
164
+ console.log('\nAnnotation saved successfully!');
165
+ break;
166
+ }
167
+ }
168
+ catch (error) {
169
+ this.error(`Failed to save annotation: ${error}`);
170
+ }
171
+ }
172
+ }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ import { RainbowAuthService } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1
7
7
  import { type RaindropState } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/raindrop_pb';
8
8
  import { SearchAgentService } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/search_agent_pb';
9
9
  import { StrictClient } from './strict-client.js';
10
+ import { AnnotationService } from '@liquidmetal-ai/protogen2/annotation_pb';
10
11
  export { run } from '@oclif/core';
11
12
  export declare const EPOCH_TS: import("@bufbuild/protobuf/wkt").Timestamp;
12
13
  export declare function configFromAppFile(appFile: string): Promise<Application[]>;
@@ -35,6 +36,7 @@ export declare function rainbowAuthService(baseUrl: string): Promise<{
35
36
  export declare function catalogService(opts: ServiceClientOptions): Promise<ServiceClient<typeof CatalogService>>;
36
37
  export declare function searchAgentService(opts: ServiceClientOptions): Promise<ServiceClient<typeof SearchAgentService>>;
37
38
  export declare function objectService(opts: ServiceClientOptions): Promise<ServiceClient<typeof ObjectService>>;
39
+ export declare function annotationService(opts: ServiceClientOptions): Promise<ServiceClient<typeof AnnotationService>>;
38
40
  export type ServiceClientOptions = {
39
41
  rainbowAuth: StrictClient<typeof RainbowAuthService>;
40
42
  configDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ import { fileURLToPath } from 'node:url';
16
16
  import semver from 'semver';
17
17
  import { createStrictClient } from './strict-client.js';
18
18
  import { traceStore } from './trace.js';
19
+ import { AnnotationService } from '@liquidmetal-ai/protogen2/annotation_pb';
19
20
  export { run } from '@oclif/core';
20
21
  export const EPOCH_TS = timestampFromDate(new Date(0));
21
22
  export async function configFromAppFile(appFile) {
@@ -190,6 +191,9 @@ export async function searchAgentService(opts) {
190
191
  export async function objectService(opts) {
191
192
  return serviceClient(ObjectService, opts);
192
193
  }
194
+ export async function annotationService(opts) {
195
+ return serviceClient(AnnotationService, opts);
196
+ }
193
197
  export async function serviceClient(service, { rainbowAuth, configDir, identity, overrideAuthToken, logger, enableSendVersion }) {
194
198
  const { baseUrl, organizationId, userId } = identity;
195
199
  const { authenticate } = createAuthenticateInterceptor(configDir, rainbowAuth, overrideAuthToken);
@@ -1 +1 @@
1
- {"root":["../src/base-command.ts","../src/build.test.ts","../src/build.ts","../src/codegen.test.ts","../src/codegen.ts","../src/config.test.ts","../src/config.ts","../src/deploy.ts","../src/index.test.ts","../src/index.ts","../src/strict-client.ts","../src/trace.ts","../src/commands/tail.ts","../src/commands/auth/list.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/select.ts","../src/commands/build/branch.ts","../src/commands/build/checkout.ts","../src/commands/build/clone.ts","../src/commands/build/delete.ts","../src/commands/build/deploy.ts","../src/commands/build/find.ts","../src/commands/build/generate.ts","../src/commands/build/init.ts","../src/commands/build/list.ts","../src/commands/build/sandbox.ts","../src/commands/build/start.ts","../src/commands/build/status.ts","../src/commands/build/stop.ts","../src/commands/build/unsandbox.ts","../src/commands/build/upload.ts","../src/commands/build/validate.ts","../src/commands/build/env/get.ts","../src/commands/build/env/set.ts","../src/commands/build/tools/check.ts","../src/commands/build/tools/fmt.ts","../src/commands/object/delete.ts","../src/commands/object/get.ts","../src/commands/object/list.ts","../src/commands/object/put.ts","../src/commands/query/chunk-search.ts","../src/commands/query/document.ts","../src/commands/query/search.ts"],"version":"5.8.2"}
1
+ {"root":["../src/base-command.ts","../src/build.test.ts","../src/build.ts","../src/codegen.test.ts","../src/codegen.ts","../src/config.test.ts","../src/config.ts","../src/deploy.ts","../src/index.test.ts","../src/index.ts","../src/strict-client.ts","../src/trace.ts","../src/commands/tail.ts","../src/commands/annotation/get.ts","../src/commands/annotation/list.ts","../src/commands/annotation/put.ts","../src/commands/auth/list.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/select.ts","../src/commands/build/branch.ts","../src/commands/build/checkout.ts","../src/commands/build/clone.ts","../src/commands/build/delete.ts","../src/commands/build/deploy.ts","../src/commands/build/find.ts","../src/commands/build/generate.ts","../src/commands/build/init.ts","../src/commands/build/list.ts","../src/commands/build/sandbox.ts","../src/commands/build/start.ts","../src/commands/build/status.ts","../src/commands/build/stop.ts","../src/commands/build/unsandbox.ts","../src/commands/build/upload.ts","../src/commands/build/validate.ts","../src/commands/build/env/get.ts","../src/commands/build/env/set.ts","../src/commands/build/tools/check.ts","../src/commands/build/tools/fmt.ts","../src/commands/object/delete.ts","../src/commands/object/get.ts","../src/commands/object/list.ts","../src/commands/object/put.ts","../src/commands/query/chunk-search.ts","../src/commands/query/document.ts","../src/commands/query/search.ts"],"version":"5.8.2"}